<?php

/**
 * Copyright 2024-2025 Simply.IN Sp. z o.o.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the EUPL-1.2 or later.
 * You may not use this work except in compliance with the Licence.
 *
 * Copy of the Licence is available at:
 * https://joinup.ec.europa.eu/software/page/eupl
 * It is bundled with this package in the file LICENSE.txt
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the Licence is distributed on an as is basis,
 * without warranties or conditions of any kind, either express or implied.
 * Check the Licence for the specific language governing permissions
 * and limitations under the License.
 *
 * @author   Simply.IN Sp. z o.o.
 * @copyright 2024-2025 Simply.IN Sp. z o.o.
 * @license   https://joinup.ec.europa.eu/software/page/eupl
 */

declare(strict_types=1);

namespace SimplyIn\Payment;

use Cart;
use Configuration;
use Context;
use Currency;
use Media;
use Module;
use PaymentModule;
use PrestaShop\PrestaShop\Core\Payment\PaymentOption;

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

final class PaymentOptionsBuilder
{
    public function __construct(
        private readonly PaymentLogoResolver $logoResolver,
        private readonly PaymentMethodsProvider $methodsProvider,
        private readonly PaywallRenderer $paywallRenderer,
    ) {
    }

    /**
     * @return array<int, PaymentOption>
     */
    public function build(Module $module, Cart $cart): array
    {
        if (!($module instanceof PaymentModule)) {
            return [];
        }
        if (!$this->hasCurrencyEnabled($module, $cart)) {
            return [];
        }
        if (!$module->active || !Configuration::get('SIMPLYIN_PAYMENTS')) {
            return [];
        }

        $methods = $this->methodsProvider->getAvailableMethods();
        if ($methods === []) {
            return [];
        }

        $context = Context::getContext();
        $currencyIso = (string) ($context->currency->iso_code ?? '');

        // Computed once for the whole paywall rather than per provider block - it does not vary
        // between them.
        $extraVars = ['total' => $this->formatTotal($module, $cart, $currencyIso)];

        $options = [];
        foreach ($this->paywallRenderer->prepare($methods, $currencyIso) as $providerMethods) {
            $additionalInformation = $this->paywallRenderer->renderBlock($module, $providerMethods, $extraVars);
            $logo = $this->logoResolver->resolve($providerMethods);

            $option = new PaymentOption();
            $option->setModuleName($module->name)
                ->setCallToActionText($module->l('Simple and Safe payments'))
                ->setAction($context->link->getModuleLink($module->name, 'validation', [], true))
                ->setAdditionalInformation($additionalInformation);

            if ($logo !== null) {
                $mediaPath = Media::getMediaPath(_MODULE_DIR_ . $module->name . '/views/img/' . $logo);
                $option->setLogo(is_string($mediaPath) ? $mediaPath : '');
            }

            $options[] = $option;
        }

        return $options;
    }

    private function hasCurrencyEnabled(PaymentModule $module, Cart $cart): bool
    {
        $currencyOrder = new Currency($cart->id_currency);
        $currenciesModule = $module->getCurrency($cart->id_currency);

        if (!is_array($currenciesModule)) {
            return false;
        }

        foreach ($currenciesModule as $currencyModule) {
            if ((int) $currencyOrder->id === (int) $currencyModule['id_currency']) {
                return true;
            }
        }

        return false;
    }

    /**
     * The cart total, the one paywall variable that is specific to the checkout.
     */
    private function formatTotal(Module $module, Cart $cart, string $currencyIso): string
    {
        return sprintf(
            $module->l('%1$s (tax incl.)'),
            Context::getContext()->getCurrentLocale()->formatPrice(
                $cart->getOrderTotal(true, Cart::BOTH),
                $currencyIso,
            ),
        );
    }
}
