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

use InPost\International\Entity\PickupAddress;
use InPost\International\PickupAddress\PickupAddressRepositoryInterface;
use InPost\International\PickupOrder\DTO\PickupTime;
use InPost\International\PickupOrder\Message\CreatePickupOrderCommand;
use InPost\International\PickupOrder\Util\CutoffPickupTimeChecker;
use Psr\Clock\ClockInterface;

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

class PickupOrderCommandFactory
{
    /**
     * @var PickupAddressRepositoryInterface
     */
    private $addressRepository;

    /**
     * @var CutoffPickupTimeChecker
     */
    private $cutoffTimeChecker;

    /**
     * @var ClockInterface
     */
    private $clock;

    public function __construct(PickupAddressRepositoryInterface $addressRepository, CutoffPickupTimeChecker $cutoffTimeChecker, ClockInterface $clock)
    {
        $this->addressRepository = $addressRepository;
        $this->cutoffTimeChecker = $cutoffTimeChecker;
        $this->clock = $clock;
    }

    public function createCommand(int ...$shipmentIds): CreatePickupOrderCommand
    {
        $address = $this->addressRepository->getDefault();
        $pickupTime = $this->getPickupTime($address);

        return (new CreatePickupOrderCommand())
            ->setShipmentIds($shipmentIds)
            ->setPickupAddress($address)
            ->setPickupDate($pickupTime->getFrom())
            ->setPickupTime($pickupTime);
    }

    private function getPickupTime(?PickupAddress $address): PickupTime
    {
        $date = $this->getNextWorkday();
        $from = $date->setTime(9, 0);

        if (null === $address || null === $cutoffTime = $this->cutoffTimeChecker->check($address)) {
            $to = $date->setTime(17, 0);
        } else {
            $to = $cutoffTime
                ->setDate((int) $date->format('Y'), (int) $date->format('m'), (int) $date->format('d'))
                ->modify('-1 minute');
        }

        return new PickupTime($from, $to);
    }

    private function getNextWorkday(): \DateTimeImmutable
    {
        $date = $this->clock->now();

        do {
            $date = $date->modify('+1 day');
        } while ($date->format('N') > 5);

        return $date;
    }
}
