<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\MessageHandler\Order;

use Gls\GlsPoland\PrestaShop\Hook\HookDispatcherInterface;
use Gls\GlsPoland\PrestaShop\Message\SendTrackingUrlEmailCommand;
use Gls\GlsPoland\PrestaShop\ObjectModel\Repository\CustomerRepository;
use Gls\GlsPoland\PrestaShop\ObjectModel\Repository\OrderCarrierRepository;
use Gls\GlsPoland\PrestaShop\ObjectModel\Repository\OrderRepository;
use PrestaShop\PrestaShop\Core\CommandBus\CommandBusInterface;
use PrestaShop\PrestaShop\Core\Domain\Order\Command\UpdateOrderShippingDetailsCommand;
use PrestaShop\PrestaShop\Core\Exception\CoreException;

final class SendTrackingUrlEmailHandler implements SendTrackingUrlEmailHandlerInterface
{
    private $bus;
    private $orderRepository;
    private $orderCarrierRepository;
    private $customerRepository;
    private $hookDispatcher;

    public function __construct(CommandBusInterface $bus, OrderRepository $orderRepository, OrderCarrierRepository $orderCarrierRepository, CustomerRepository $customerRepository, HookDispatcherInterface $hookDispatcher)
    {
        $this->bus = $bus;
        $this->orderRepository = $orderRepository;
        $this->orderCarrierRepository = $orderCarrierRepository;
        $this->customerRepository = $customerRepository;
        $this->hookDispatcher = $hookDispatcher;
    }

    public function handle(SendTrackingUrlEmailCommand $command): void
    {
        $orderCarrier = $command->getOrderCarrier();

        if (class_exists(UpdateOrderShippingDetailsCommand::class)) {
            $nativeCommand = new UpdateOrderShippingDetailsCommand(
                (int) $orderCarrier->id_order,
                (int) $orderCarrier->id,
                (int) $command->getCarrier()->id,
                $command->getParcelNumber()
            );

            $this->bus->handle($nativeCommand);
        } else {
            $this->doHandle($orderCarrier, $command->getCarrier(), $command->getParcelNumber());
        }
    }

    private function doHandle(\OrderCarrier $orderCarrier, \Carrier $carrier, string $parcelNumber): void
    {
        if (null === $order = $this->orderRepository->find((int) $orderCarrier->id)) {
            return;
        }

        $orderCarrier->tracking_number = $parcelNumber;
        $this->orderCarrierRepository->update($orderCarrier);

        if (!$orderCarrier->sendInTransitEmail($order)) {
            throw new CoreException('An error occurred while sending an email to the customer.');
        }

        $this->hookDispatcher->dispatch('actionAdminOrdersTrackingNumberUpdate', [
            'order' => $order,
            'customer' => $this->customerRepository->find((int) $order->id_customer),
            'carrier' => $carrier,
        ], (int) $order->id_shop);
    }
}
