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

use InPost\International\Api\Shipment\Model\Parcel\ParcelType;
use InPost\International\Entity\ParcelTemplate;
use InPost\International\ParcelTemplate\DimensionsMapper;
use InPost\International\ParcelTemplate\Exception\ParcelTemplateException;
use InPost\International\ParcelTemplate\Message\CreateParcelTemplateCommand;
use InPost\International\ParcelTemplate\ParcelTemplateRepositoryInterface;
use InPost\International\Shipment\Exception\ParcelException;

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

final class CreateParcelTemplateHandler
{
    /**
     * @var ParcelTemplateRepositoryInterface
     */
    private $repository;

    /**
     * @var DimensionsMapper
     */
    private $mapper;

    public function __construct(ParcelTemplateRepositoryInterface $repository, DimensionsMapper $mapper)
    {
        $this->repository = $repository;
        $this->mapper = $mapper;
    }

    public function __invoke(CreateParcelTemplateCommand $command): ParcelTemplate
    {
        try {
            $template = $this->createParcelTemplate($command);
        } catch (ParcelException $e) {
            throw new ParcelTemplateException($e->getMessage(), 0, $e);
        }

        if (null === $defaultTemplate = $this->repository->getDefault()) {
            $template->setDefault(true);
        } elseif ($command->isDefault()) {
            $defaultTemplate->setDefault(false);
            $template->setDefault(true);
        }

        $this->repository->add($template);

        return $template;
    }

    public function handle(CreateParcelTemplateCommand $command): ParcelTemplate
    {
        return ($this)($command);
    }

    private function createParcelTemplate(CreateParcelTemplateCommand $command): ParcelTemplate
    {
        if (null === $dimensions = $command->getDimensions()) {
            throw new ParcelTemplateException('Dimensions are required.');
        }

        if (null === $weight = $command->getWeight()) {
            throw new ParcelTemplateException('Weight is required.');
        }

        return new ParcelTemplate(
            (string) $command->getName(),
            $command->getType() ?? ParcelType::Standard(),
            $this->mapper->mapDtoToDimensions($dimensions),
            $this->mapper->mapDtoToWeight($weight)
        );
    }
}
