<?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\Order\EventListener;

use InPost\International\PrestaShop\ObjectModel\ObjectManagerInterface;
use InPost\International\Shipment\Event\ShipmentCreatedEvent;
use PrestaShop\PrestaShop\Core\CommandBus\CommandBusInterface;
use PrestaShop\PrestaShop\Core\Domain\Order\Command\UpdateOrderShippingDetailsCommand;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

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

final class SendTrackingUrlMailListener implements EventSubscriberInterface
{
    /**
     * @var ObjectManagerInterface
     */
    private $manager;

    /**
     * @var CommandBusInterface
     */
    private $bus;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(ObjectManagerInterface $manager, CommandBusInterface $bus, LoggerInterface $logger)
    {
        $this->manager = $manager;
        $this->bus = $bus;
        $this->logger = $logger;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ShipmentCreatedEvent::class => 'onShipmentCreated',
        ];
    }

    public function onShipmentCreated(ShipmentCreatedEvent $event): void
    {
        $orderId = $event->getShipment()->getOrderId();
        $trackingNumber = $event->getShipment()->getTrackingNumber();

        // subscribing to the "kernel.terminate" event might cause problems
        // if the container cache is not rebuilt after disabling/uninstalling the module
        register_shutdown_function(function () use ($orderId, $trackingNumber) {
            $this->processOrder($orderId, $trackingNumber);
        });
    }

    private function processOrder(int $orderId, string $trackingNumber): void
    {
        $orderCarrier = $this->manager->getRepository(\OrderCarrier::class)->findOneBy(['id_order' => $orderId]);

        if (null === $orderCarrier) {
            return;
        }

        $carrier = $this->manager->find(\Carrier::class, (int) $orderCarrier->id_carrier);

        if (null === $carrier || \InPostInternational::MODULE_NAME !== $carrier->external_module_name) {
            return;
        }

        try {
            $this->bus->handle(new UpdateOrderShippingDetailsCommand(
                $orderId,
                (int) $orderCarrier->id,
                (int) $carrier->id,
                $trackingNumber
            ));
        } catch (\Throwable $e) {
            $this->logger->error('Failed to send tracking email for order #{orderId}, tracking number: "{trackingNumber}".', [
                'orderId' => $orderId,
                'trackingNumber' => $trackingNumber,
                'exception' => $e,
            ]);
        }
    }
}
