<?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\Checkout\Form;

use InPost\International\Checkout\Exception\CheckoutException;
use InPost\International\Checkout\Exception\FormValidationException;
use InPost\International\HttpFoundation\RequestHelper;
use PrestaShop\PrestaShop\Core\CommandBus\CommandBusInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
use Symfony\Component\HttpFoundation\Request;

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

final class DeliveryFormHandler implements DeliveryFormHandlerInterface
{
    /**
     * @var DeliveryOptionsFormFactoryInterface
     */
    private $formFactory;

    /**
     * @var CommandBusInterface
     */
    private $commandBus;

    public function __construct(DeliveryOptionsFormFactoryInterface $formFactory, CommandBusInterface $commandBus)
    {
        $this->formFactory = $formFactory;
        $this->commandBus = $commandBus;
    }

    public function handle(\Cart $cart, Request $request): void
    {
        $deliveryOption = $this->getDeliveryOption($request);

        if (null === $form = $this->formFactory->getForDeliveryOption($cart, $deliveryOption)) {
            return;
        }

        $this->handleRequest($form, $request);
        $this->commandBus->handle($form->getData());
    }

    private function getDeliveryOption(Request $request): array
    {
        if (!$request->request->has('delivery_option')) {
            throw new CheckoutException('Malformed request: "delivery_option" is missing.');
        }

        try {
            $deliveryOption = RequestHelper::getAll($request->request, 'delivery_option');
        } catch (RequestExceptionInterface $e) {
            throw new CheckoutException('Malformed request: "delivery_option" is invalid.', 0, $e);
        }

        return $deliveryOption;
    }

    private function handleRequest(FormInterface $form, Request $request): void
    {
        if (0 === count($form)) {
            return;
        }

        $form->handleRequest($request);

        if (!$form->isSubmitted()) {
            throw new CheckoutException(sprintf('Malformed request: "%s" is missing.', $form->getName()));
        }

        if (!$form->isValid()) {
            throw new FormValidationException($form->getErrors(true));
        }
    }
}
