<?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\PaymentMethod\Widget\Logo\Widget as LogoWidget;
use Resursbank\Ecom\Module\PaymentMethod\Widget\ReadMore;
use Resursbank\Ecom\Module\PaymentMethod\Widget\UniqueSellingPoint;
use Resursbank\Ecom\Module\PriceSignage\Repository as SignageRepository;
use Resursbank\Ecom\Module\PriceSignage\Widget\CostList;
use Resursbank\Ecom\Module\PriceSignage\Widget\Warning;
use Resursbank\MerchantApi\Util\Log;
use Throwable;

/**
 * Hook handler that fetches Resurs payment methods.
 */
class PaymentOptions
{
    /**
     * @return array Payment methods
     */
    public static function exec(): array
    {
        $result = [];

        try {
            $context = Context::getContext();
            $cartTotal = (float)$context->cart->getOrderTotal();
            $billingAddress = new 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
                )) {
                    continue;
                }

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

                $priceSignage = self::getPriceSignage(
                    paymentMethod: $method,
                    amount: $cartTotal
                );

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

                $option = new PaymentOption();
                $option->setCallToActionText(callToActionText: $method->name)
                    ->setModuleName(moduleName: 'resursbank')
                    ->setAdditionalInformation(
                        additionalInformation: '<div class="rb-pm-info">' .
                        '<div class="rb-pm-usp">' . $usp->message . '</div>' .
                        '<style>' . $readMoreWidget->css . '</style>' .
                        '<div class="rb-ps-cl-container">'.
                        $costListContent .
                        '</div>' .
                        '<div class="rb-pm-link">' . $readMoreWidget->content .
                        '</div>' .
                        '<div class="rb-warning">' .
                        $warningContent .
                        '</div>' .
                        '</div>'
                    )
                    ->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) {
            // @todo Add a flash message in frontend?
            Log::error(message: $error);
        }

        return $result;
    }

    /**
     * Fetch price signage or null if not internal method.
     *
     * @param PaymentMethod $paymentMethod
     * @param float $amount
     * @return PriceSignage|null
     */
    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::error(message: $error);
        }

        return null;
    }

    /**
     * Check if payment method is available.
     *
     * @param PaymentMethod $method
     * @param bool $isCompany
     * @param float $cartTotal
     * @return bool
     */
    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;
    }
}
