<?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\Shipment\MessageHandler;

use InPost\International\Api\Exception\ApiClientExceptionInterface;
use InPost\International\Api\Shipment\ShipmentsApiClientInterface;
use InPost\International\File\Base64EncodedFile;
use InPost\International\File\StreamableInterface;
use InPost\International\Shipment\Event\LabelPrintedEvent;
use InPost\International\Shipment\Exception\ShipmentException;
use InPost\International\Shipment\Exception\ShipmentNotFoundException;
use InPost\International\Shipment\Message\PrintLabelCommand;
use InPost\International\Shipment\ShipmentRepositoryInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

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

final class PrintLabelHandler
{
    /**
     * @var ShipmentRepositoryInterface
     */
    private $repository;

    /**
     * @var ShipmentsApiClientInterface
     */
    private $client;

    /**
     * @var EventDispatcherInterface
     */
    private $dispatcher;

    public function __construct(ShipmentRepositoryInterface $repository, ShipmentsApiClientInterface $client, EventDispatcherInterface $dispatcher)
    {
        $this->repository = $repository;
        $this->client = $client;
        $this->dispatcher = $dispatcher;
    }

    /**
     * @throws ShipmentException
     * @throws ApiClientExceptionInterface
     */
    public function __invoke(PrintLabelCommand $command): StreamableInterface
    {
        if (null === $shipment = $this->repository->find($command->getShipmentId())) {
            throw ShipmentNotFoundException::create($command->getShipmentId());
        }

        $label = $this->client->getShipmentLabel($shipment->getUuid());
        $this->dispatcher->dispatch(new LabelPrintedEvent($shipment));

        return new Base64EncodedFile(
            $label->getLabel()->getContent(),
            'application/pdf',
            sprintf('%s.pdf', $shipment->getTrackingNumber())
        );
    }

    public function handle(PrintLabelCommand $command): StreamableInterface
    {
        return ($this)($command);
    }
}
