<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Checkout\EventListener;

use InPost\International\Asset\AssetManagerInterface;
use InPost\International\Asset\Event\FrontControllerAssetsRegisteredEvent;
use InPost\International\Checkout\CheckoutInterface;
use InPost\International\Checkout\CheckoutResolverInterface;
use InPost\International\Checkout\Event\CarrierProcessEvent;
use InPost\International\Checkout\Event\DisplayCarrierContentEvent;
use InPost\International\Checkout\Event\StepCompleteValidationEvent;
use InPost\International\EventDispatcher\Util\SubscriberUtil;
use InPost\International\Hook\Event\HookInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

if (!defined('_PS_VERSION_')) {
    exit;
}

final class DeliveryStepListener implements EventSubscriberInterface
{
    /**
     * @var CheckoutResolverInterface
     */
    private $resolver;

    /**
     * @var AssetManagerInterface
     */
    private $assetManager;

    public function __construct(CheckoutResolverInterface $resolver, AssetManagerInterface $assetManager)
    {
        $this->resolver = $resolver;
        $this->assetManager = $assetManager;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            FrontControllerAssetsRegisteredEvent::NAME => 'onControllerAssetsRegistered',
            DisplayCarrierContentEvent::NAME => 'onDisplayCarrierContent',
            StepCompleteValidationEvent::NAME => 'onStepCompleteValidation',
            CarrierProcessEvent::NAME => 'onCarrierProcess',
        ];
    }

    public function onControllerAssetsRegistered(FrontControllerAssetsRegisteredEvent $event): void
    {
        $request = $event->getRequest();

        if (null === $request || $request->isXmlHttpRequest()) {
            return;
        }

        if (null === $checkout = $this->resolver->resolve($request)) {
            return;
        }

        $this->assetManager->registerAssets($checkout->getAssets());
    }

    public function onDisplayCarrierContent(DisplayCarrierContentEvent $event): void
    {
        $request = $event->getRequest();

        if (null === $checkout = $this->resolver->resolve($request)) {
            return;
        }

        $content = $checkout->renderView(
            $request,
            $event->getCart(),
            $event->getCarrierId()
        );

        $event->appendContent($content);
    }

    public function onStepCompleteValidation(StepCompleteValidationEvent $event): void
    {
        if ('delivery' !== $event->getStepName() || !$event->isCompleted()) {
            return;
        }

        if (null === $checkout = $this->resolver->resolve($event->getRequest())) {
            return;
        }

        $this->propagateEvent($checkout, $event);
    }

    public function onCarrierProcess(CarrierProcessEvent $event): void
    {
        if (null === $checkout = $this->resolver->resolve($event->getRequest())) {
            return;
        }

        $this->propagateEvent($checkout, $event);
    }

    private function propagateEvent(CheckoutInterface $checkout, HookInterface $event): void
    {
        $listeners = $checkout->getSubscribedEvents();

        if ([] === $listeners = $listeners[$event->getName()] ?? []) {
            return;
        }

        $listeners = SubscriberUtil::normalizeListeners($listeners);
        usort($listeners, static function (array $a, array $b) {
            return $b[1] <=> $a[1];
        });

        foreach ($listeners as $listener) {
            $checkout->{$listener[0]}($event);
        }
    }
}
