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

use InPost\International\PrestaShop\Module\ModuleRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\Service\ServiceProviderInterface;

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

final class CheckoutResolver implements CheckoutResolverInterface
{
    /**
     * @var ServiceProviderInterface
     */
    private $container;

    /**
     * @var \Context
     */
    private $context;

    /**
     * @var ModuleRepository
     */
    private $moduleRepository;

    /**
     * @var array{checkout?: CheckoutInterface|null}
     */
    private $cache = [];

    /**
     * @param ServiceProviderInterface $container service provider of {@see CheckoutInterface}
     */
    public function __construct(ServiceProviderInterface $container, \Context $context, ModuleRepository $moduleRepository)
    {
        $this->container = $container;
        $this->context = $context;
        $this->moduleRepository = $moduleRepository;
    }

    public function resolve(Request $request): ?CheckoutInterface
    {
        if (array_key_exists('checkout', $this->cache)) {
            return $this->cache['checkout'];
        }

        return $this->cache['checkout'] = $this->doResolve($request);
    }

    private function doResolve(Request $request): ?CheckoutInterface
    {
        $controller = $this->context->controller;
        assert($controller instanceof \FrontControllerCore);

        foreach ($this->container->getProvidedServices() as $id => $type) {
            if ('?' === $type[0]) {
                $type = substr($type, 1);
            }

            if ('' === $type) {
                $type = (string) $id;
            }

            if (!$this->isCurrentCheckout($type, $controller, $request)) {
                continue;
            }

            return $this->container->get($id);
        }

        return null;
    }

    private function isCurrentCheckout(string $type, \FrontControllerCore $controller, Request $request): bool
    {
        if (!is_subclass_of($type, CheckoutInterface::class)) {
            throw new \InvalidArgumentException(sprintf('Type "%s" must implement "%s".', $type, CheckoutInterface::class));
        }

        if (!$type::supports($controller, $request)) {
            return false;
        }

        if (!is_subclass_of($type, ModuleCheckoutInterface::class)) {
            return true;
        }

        return $this->moduleRepository->isEnabled($type::getModuleName());
    }
}
