<?php

/**
 * Copyright © Resurs Bank AB. All rights reserved.
 * See LICENSE for license details.
 */

namespace Resursbank\MerchantApi\Hook;

use Address;
use Context;
use PrestaShop\PrestaShop\Core\Payment\PaymentOption;
use Resursbank\Ecom\Lib\Model\PaymentMethod;
use Resursbank\Ecom\Lib\Model\PriceSignage\PriceSignage;
use Resursbank\Ecom\Module\PaymentMethod\Repository;
use Resursbank\Ecom\Module\PriceSignage\Repository as SignageRepository;
use Resursbank\Ecom\Module\Widget\ConsumerCreditWarning\Html as ConsumerCreditWarning;
use Resursbank\Ecom\Module\Widget\CostList\Html as CostList;
use Resursbank\Ecom\Module\Widget\Logo\Html as LogoWidget;
use Resursbank\Ecom\Module\Widget\ReadMore\Html as ReadMoreWidget;
use Resursbank\Ecom\Module\Widget\UniqueSellingPoint\Html as UniqueSellingPoint;
use Resursbank\MerchantApi\Util\Log;
use Throwable;

/**
 * Hook handler that fetches Resurs payment methods for PrestaShop.
 *
 * PrestaShop splits payment method markup into fixed containers.
 *
 *   1. USP  (without internal read-more link)
 *   2. CostList
 *   3. ReadMore widget (single link)
 *   4. Consumer credit warning
 *
 * All CSS/JS assets are handled globally in HeaderAssets::hookHeader().
 */
class PaymentOptions
{
    /**
     * @return array Payment methods
     */
    public static function exec(): array
    {
        $result = [];

        try {
            $context = Context::getContext();
            $cartTotal = (float)$context->cart->getOrderTotal();
            $billingAddress = new Address(id_address: $context->cart->id_address_invoice);
            $isCompany = !empty($billingAddress->company);

            /** @var PaymentMethod $method */
            foreach (Repository::getPaymentMethods() as $method) {

                if (!self::isAvailable(method: $method, isCompany: $isCompany, cartTotal: $cartTotal)) {
                    // Method not eligible based on config / company type / price range
                    continue;
                }

                // Widgets
                $usp = new UniqueSellingPoint(paymentMethod: $method, amount: $cartTotal);
                $readMoreWidget = new ReadMoreWidget(paymentMethod: $method, amount: $cartTotal);
                $logo = new LogoWidget(paymentMethod: $method);

                // Price signage content
                $priceSignage = self::getPriceSignage(paymentMethod: $method, amount: $cartTotal);
                $warningContent = '';
                $costListContent = '';

                if ($priceSignage !== null) {
                    $warningContent = (new ConsumerCreditWarning(paymentMethod: $method))->content;
                    $costListContent = (new CostList(priceSignage: $priceSignage, method: $method))->content;
                }

                /**
                 * PrestaShop layout:
                 *
                 * 1. USP
                 * 2. Costlist
                 * 3. ReadMore link (single)
                 * 4. Warning
                 */
                $additionalHtml =
                    '<div class="rb-wrapper">' .
                    '<div class="rb-usp">' . $usp->getText() . '</div>' .
                    '<div class="rb-costlist">' . $costListContent . '</div>' .
                    '<div class="rb-readmore">' . $readMoreWidget->content . '</div>' .
                    '<div class="rb-warning">' . $warningContent . '</div>' .
                    '</div>';

                // Build payment option
                $option = new PaymentOption();
                $option
                    ->setCallToActionText(callToActionText: $method->name)
                    ->setModuleName(moduleName: 'resursbank')
                    ->setAdditionalInformation(additionalInformation: $additionalHtml)
                    ->setLogo(logo: $logo->getLogo(inclImgTag: false))
                    ->setAction(
                        action: $context->link->getModuleLink(
                            module: 'resursbank',
                            controller: 'validation',
                            params: ['payment_method_id' => $method->id],
                            ssl: true
                        )
                    );

                $result[] = $option;
            }

            return $result;

        } catch (Throwable $error) {
            // Log unexpected exception to protect checkout stability
            Log::error(message: $error);
        }

        return $result;
    }

    /**
     * Fetch price signage or null if not internal method.
     */
    private static function getPriceSignage(PaymentMethod $paymentMethod, float $amount): ?PriceSignage
    {
        try {
            if ($paymentMethod->priceSignagePossible && $paymentMethod->isInternal()) {
                return SignageRepository::getPriceSignage(
                    paymentMethodId: $paymentMethod->id,
                    amount: $amount
                );
            }
        } catch (Throwable $error) {
            // Log unexpected exception to protect checkout stability
            Log::error(message: $error);
        }

        return null;
    }

    /**
     * Check if the payment method is available.
     */
    private static function isAvailable(PaymentMethod $method, bool $isCompany, float $cartTotal): bool
    {
        // Confirm if method is available based on customer type.
        if (
            ($isCompany && !$method->enabledForLegalCustomer) ||
            (!$isCompany && !$method->enabledForNaturalCustomer)
        ) {
            return false;
        }

        // Confirm min/max purchase limits against cart total.
        if ($method->minPurchaseLimit > $cartTotal ||
            $method->maxPurchaseLimit < $cartTotal
        ) {
            return false;
        }

        return true;
    }
}
