<?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\Asset\Provider;

use InPost\International\Asset\Assets;
use InPost\International\Configuration\Repository\ApiConfigurationRepositoryInterface;
use InPost\International\Http\Util\UriResolver;

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

final class GeoWidgetAssetsProvider implements AssetsProviderInterface
{
    public const GEO_WIDGET_CONFIG_VAR_NAME = 'inPostIntlGeoWidgetConfig';

    private const GEO_WIDGET_JS_URI = 'inpost-geowidget.js';
    private const GEO_WIDGET_CSS_URI = 'inpost-geowidget.css';

    /**
     * @var ApiConfigurationRepositoryInterface
     */
    private $repository;

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

    public function __construct(ApiConfigurationRepositoryInterface $repository, \Context $context)
    {
        $this->repository = $repository;
        $this->context = $context;
    }

    public function getAssets(): Assets
    {
        $configuration = $this->repository->getConfiguration();

        if (null === $token = $configuration->getGeoWidgetToken()) {
            return new Assets();
        }

        $geoWidgetBaseUri = $configuration->getEnvironment()->getGeoWidgetUri();

        // Both the INTL and domestic GeoWidget libraries attempt to define a custom HTML element with the same tag name.
        // We must ensure that the INTL script executes before the domestic one because the INTL map allows
        // selecting both international and domestic points, while the domestic one can only display domestic points.
        // This conflict can also cause issues when modules run in different modes or when both run in test mode,
        // as the set of available points may differ. At the moment, we cannot avoid this.
        return (new Assets())
            // "Fixes" the point ID format to match the domestic GeoWidget when the widget is initialized
            // without the "country" parameter.
            ->addJavaScript('js/front/geo-widget-compatibility.js', [
                'position' => 'head',
            ])
            // The official GeoWidget documentation recommends adding the script in the head with the defer attribute.
            // However, some third-party modules (e.g. `sensbitinpost`) add the domestic widget script in the footer
            // without defer or async. To maintain compatibility and ensure the INTL widget is defined first, we have to
            // add the INTL script without defer as well.
            ->addJavaScript(UriResolver::resolve(self::GEO_WIDGET_JS_URI, $geoWidgetBaseUri))
            /* ->addJavaScript(UriResolver::resolve(self::GEO_WIDGET_JS_URI, $geoWidgetBaseUri), [
                'position' => 'head',
                'attributes' => 'defer',
                'priority' => 40,
            ]) */
            ->addStyleSheet(UriResolver::resolve(self::GEO_WIDGET_CSS_URI, $geoWidgetBaseUri))
            ->addJavaScriptVariable(self::GEO_WIDGET_CONFIG_VAR_NAME, [
                'token' => $token,
                'language' => $this->context->language->iso_code,
            ]);
    }
}
