<?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 Doctrine\ORM\EntityManagerInterface;
use InPost\International\Entity\Dimensions;
use InPost\International\Entity\ParcelTemplate;
use InPost\International\Entity\Weight;
use InPost\International\ParcelTemplate\DimensionsMapper;
use InPost\International\ParcelTemplate\Exception\ParcelTemplateNotFoundException;
use InPost\International\ParcelTemplate\Message\EditParcelTemplateCommand;
use InPost\International\ParcelTemplate\ParcelTemplateRepositoryInterface;

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

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

    /**
     * @var EntityManagerInterface
     */
    private $entityManager;

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

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

    public function __invoke(EditParcelTemplateCommand $command): void
    {
        $templateId = $command->getTemplateId();

        if (null === $template = $this->repository->find($templateId)) {
            throw new ParcelTemplateNotFoundException('Parcel template does not exist.');
        }

        if (false === $command->isDefault() && $template->isDefault()) {
            throw new ParcelTemplateNotFoundException('Cannot unset default parcel template.');
        }

        if (null !== $name = $command->getName()) {
            $template->setName($name);
        }

        if (null !== $type = $command->getType()) {
            $template->setType($type);
        }

        if (null !== $dimensions = $this->getNewDimensions($command)) {
            $template->setDimensions($dimensions);
        }

        if (null !== $weight = $this->getNewWeight($command)) {
            $template->setWeight($weight);
        }

        if ($command->isDefault()) {
            $this->markAsDefaultTemplate($template);
        }

        $this->entityManager->flush();
    }

    public function handle(EditParcelTemplateCommand $command): void
    {
        ($this)($command);
    }

    private function getNewDimensions(EditParcelTemplateCommand $command): ?Dimensions
    {
        if (null === $dimensions = $command->getDimensions()) {
            return null;
        }

        return $this->mapper->mapDtoToDimensions($dimensions);
    }

    private function getNewWeight(EditParcelTemplateCommand $command): ?Weight
    {
        if (null === $weight = $command->getWeight()) {
            return null;
        }

        return $this->mapper->mapDtoToWeight($weight);
    }

    private function markAsDefaultTemplate(ParcelTemplate $template): void
    {
        if ($template->isDefault()) {
            return;
        }

        if (null !== $previousDefault = $this->repository->getDefault()) {
            $previousDefault->setDefault(false);
        }

        $template->setDefault(true);
    }
}
