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

use InPost\International\Api\Shipment\Model\ValueAddedServices;
use InPost\International\Carrier\CarrierType;
use InPost\International\Checkout\CheckoutSessionRepositoryInterface;
use InPost\International\Configuration\Repository\ShippingConfigurationRepositoryInterface;
use InPost\International\Delivery\Util\CarrierFinder;
use InPost\International\Entity\CourierCarrier;
use InPost\International\Shipment\Message\CreateShipmentCommand;

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

final class ServiceDetailsBuilder implements CreateShipmentCommandBuilderInterface
{
    /**
     * @var CarrierFinder
     */
    private $carrierFinder;

    /**
     * @var CheckoutSessionRepositoryInterface
     */
    private $checkoutSessionRepository;

    /**
     * @var ShippingConfigurationRepositoryInterface
     */
    private $configurationRepository;

    public function __construct(CarrierFinder $carrierFinder, CheckoutSessionRepositoryInterface $checkoutSessionRepository, ShippingConfigurationRepositoryInterface $configurationRepository)
    {
        $this->carrierFinder = $carrierFinder;
        $this->checkoutSessionRepository = $checkoutSessionRepository;
        $this->configurationRepository = $configurationRepository;
    }

    public function buildCommand(CreateShipmentCommand $command, \Order $order): void
    {
        if (
            self::isInsuranceAvailable($command)
            && null !== $insurance = $this->getDefaultInsurance()
        ) {
            $command->setInsurance($insurance);
        }

        if (null === $carrier = $this->carrierFinder->findOneByCarrierId((int) $order->id_carrier)) {
            return;
        }

        if ($carrier instanceof CourierCarrier) {
            $command->setService(CarrierType::Courier());

            return;
        }

        $command->setService(CarrierType::PointDelivery());

        if (null !== $checkoutSession = $this->checkoutSessionRepository->find((int) $order->id_cart)) {
            $pointId = $checkoutSession->getPointId($carrier->getReferenceId());
            $command->setDestinationPointId($pointId);
        }
    }

    private static function isInsuranceAvailable(CreateShipmentCommand $command): bool
    {
        if (null === $address = $command->getDestinationAddress()) {
            return false;
        }

        if (null === $country = $address->getCountryCode()) {
            return false;
        }

        return ValueAddedServices::isInsuranceAvailable($country);
    }

    private function getDefaultInsurance(): ?float
    {
        if (null === $configuration = $this->configurationRepository->getShippingConfiguration()) {
            return null;
        }

        if (null === $insurance = $configuration->getDefaultInsurance()) {
            return null;
        }

        return $insurance->getValue();
    }
}
