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

use InPost\International\Checkout\Form\DeliveryOptionsFormFactoryInterface;
use InPost\International\Checkout\View\Builder\CheckoutViewBuilderInterface;
use InPost\International\Checkout\View\Model\CheckoutView;
use InPost\International\Delivery\Util\CarrierFinder;
use InPost\International\Templating\RendererInterface;

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

final class CheckoutViewRenderer implements CheckoutViewRendererInterface
{
    private const DEFAULT_TEMPLATE = 'module:inpostinternational/views/templates/hook/checkout/delivery_options.tpl';

    /**
     * @var CarrierFinder
     */
    private $carrierFinder;

    /**
     * @var DeliveryOptionsFormFactoryInterface
     */
    private $formFactory;

    /**
     * @var CheckoutViewBuilderInterface
     */
    private $viewBuilder;

    /**
     * @var RendererInterface
     */
    private $renderer;

    /**
     * @var array<string, array<int, string>> content by template and carrier ID
     */
    private $cache = [];

    public function __construct(CarrierFinder $carrierFinder, DeliveryOptionsFormFactoryInterface $formFactory, CheckoutViewBuilderInterface $viewBuilder, RendererInterface $renderer)
    {
        $this->carrierFinder = $carrierFinder;
        $this->formFactory = $formFactory;
        $this->viewBuilder = $viewBuilder;
        $this->renderer = $renderer;
    }

    public function render(\Cart $cart, int $carrierId, string $template = null): string
    {
        $template = $template ?? self::DEFAULT_TEMPLATE;

        if (isset($this->cache[$template][$carrierId])) {
            return $this->cache[$template][$carrierId];
        }

        if (null === $view = $this->getView($cart, $carrierId)) {
            return $this->cache[$template][$carrierId] = '';
        }

        return $this->cache[$template][$carrierId] = $this->renderer->render($template, [
            'view' => $view,
        ]);
    }

    private function getView(\Cart $cart, int $carrierId): ?CheckoutView
    {
        if (null === $carrier = $this->carrierFinder->findOneByCarrierId($carrierId)) {
            throw new \LogicException(sprintf('Carrier ID "%d" is not associated with the InPost International module.', $carrierId));
        }

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

        $view = new CheckoutView($cart, $carrier, $carrierId, $form->createView());
        $this->viewBuilder->buildView($view);

        return $view;
    }
}
