<?php
/**
 * BookiFlex Notification Extension
 *
 * @package    BookiFlex
 * @subpackage Notification
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */


declare(strict_types=1);
namespace BookiFlex\Extensions\Notification;

use BookiFlex\Core\Repository\ReservationRepository;
use BookiFlex\Core\Service\Reservation\ReservationDetails;
use BookiFlex\Extensions\Notification\Api\Controller\NotificationController;
use BookiFlex\Extensions\Notification\Listener\ReservationSubscriber;
use BookiFlex\Extensions\Notification\Provider\CoreNotificationEventProvider;
use BookiFlex\Extensions\Notification\Provider\NotificationContextProvider;
use BookiFlex\Extensions\Notification\Repository\NotificationRepository;
use BookiFlex\Extensions\Notification\Service\EventNormalizer;
use BookiFlex\Extensions\Notification\Service\Jobs\PollDueNotificationsJob;
use BookiFlex\Extensions\Notification\Service\Jobs\PurgeOldNotificationsJob;
use BookiFlex\Extensions\Notification\Service\NotificationHandler;
use BookiFlex\Extensions\Notification\Service\NotificationRenderer;
use BookiFlex\Extensions\Notification\Service\NotificationSnapshotService;
use Cycle\ORM\EntityManagerInterface;
use Cycle\ORM\ORM;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Twig\Mime\BodyRenderer;
use Symfony\Component\Mailer\EventListener\MessageListener;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport;

defined( 'ABSPATH' ) || exit;

class ServiceProvider implements ServiceProviderInterface
{
    public function register(Container $pimple): void
    {
        $pimple[Mailer::class] = function ($c) {
			if (defined('BOOKIFLEX_TESTS_RUNNING')) {
				$transport = new Transport\NullTransport(
					$c->get('event_dispatcher'),
					$c->get(LoggerInterface::class)
				);
			} elseif (defined('BOOKIFLEX_MAILHOG_DSN') && !empty(BOOKIFLEX_MAILHOG_DSN)) {
				$transport = Transport::fromDsn(
					BOOKIFLEX_MAILHOG_DSN,
					$c->get('event_dispatcher'),
					null,
					$c->get(LoggerInterface::class)
				);
			} else {
				$transport = new Transport\SendmailTransport(
					null,
					$c->get('event_dispatcher'),
					$c->get(LoggerInterface::class)
				);
			}

            // Create Mailer with MessageBus and EventDispatcher for proper email rendering
	        return new Mailer($transport, null, $c->get('event_dispatcher'));
        };

        $pimple[BodyRenderer::class] = function ($c) {
            return new BodyRenderer($c->get('twig'));
        };

        $pimple[NotificationRepository::class] = function ($c) {
            return $c->get(ORM::class)->getRepository(\BookiFlex\Extensions\Notification\Model\Notification::class);
        };

        $pimple[EventNormalizer::class] = function ($c) {
            return new EventNormalizer();
        };

        $pimple[PollDueNotificationsJob::class] = function ($c) {
            return new PollDueNotificationsJob(
                $c->get(NotificationRepository::class),
                $c->get(NotificationHandler::class),
                $c->get(LoggerInterface::class)
            );
        };

        $pimple[PurgeOldNotificationsJob::class] = function ($c) {
            return new PurgeOldNotificationsJob(
                $c->get(NotificationRepository::class),
                $c->get(EntityManagerInterface::class),
                $c->get(LoggerInterface::class),
            );
        };

        $pimple[NotificationController::class] = function ($c) {
            return new NotificationController(
                $c->get(NotificationRepository::class),
            );
        };

        $pimple[NotificationHandler::class] = function ($c) {
            return new NotificationHandler(
                $c->get(NotificationRepository::class),
                $c->get(NotificationContextProvider::class),
                $c->get(Mailer::class),
                $c->get(EntityManagerInterface::class),
                $c->get(LoggerInterface::class)
            );
        };

        $pimple[CoreNotificationEventProvider::class] = function ($c) {
            return new CoreNotificationEventProvider();
        };

        $pimple[NotificationContextProvider::class] = function ($c) {
            $provider = new NotificationContextProvider(
                $c->get(ReservationDetails::class),
                $c->get('config')
            );
            $provider->addEventProvider($c->get(CoreNotificationEventProvider::class));

            return $provider;
        };

        $pimple[NotificationRenderer::class] = function ($c) {
            return new NotificationRenderer($c->get('twig'));
        };

        $pimple[NotificationSnapshotService::class] = function ($c) {
            return new NotificationSnapshotService(
                $c->get(NotificationContextProvider::class),
                $c->get(LoggerInterface::class),
            );
        };

        // Subscribers
        $pimple[ReservationSubscriber::class] = function ($c) {
            return new ReservationSubscriber(
                $c->get(ReservationRepository::class),
                $c->get('config'),
                $c->get(EntityManagerInterface::class),
                $c->get(EventNormalizer::class),
                $c->get(NotificationRepository::class),
                $c->get(NotificationSnapshotService::class),
                $c->get(LoggerInterface::class)
            );
        };

        $pimple[MessageListener::class] = function ($c) {
            return new MessageListener(
                null,
                new BodyRenderer($c->get('twig'))
            );
        };
    }
}
