<?php

namespace TbiBank\FusionPay\Helper;

use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Store\Model\ScopeInterface;

class Data extends AbstractHelper
{
    // Constants for URLs and file paths
    public const TBI_PLATFORM_URL = "https://ro.tbibank.support";
    public const ALLOWED_IP = "185.123.190.236";
    public const TBI_CDN_URL = "https://cdn.tbibank.support/";
    public const TBI_BANK_LOGO = "logo/tbi-bank.svg";
    public const TBI_BANK_LOGO_WHITE = "logo/tbi-bank-white.svg";
    public const TBI_BANK_LOGO_LIGHT = "logo/tbi-bank-logo2.svg";
    public const TBI_BANK_LOGO_DARK = "logo/tbi-bank.svg";
    public const TBI_LOADING_SVG = self::TBI_CDN_URL . "integrations/loading.svg";
    public const TBI_BANK_LOGO_URL = self::TBI_CDN_URL . self::TBI_BANK_LOGO_LIGHT;

    // Constants for names and URLs
    public const TBI_SHIPPING_NAME = "Livrare"; // Shipping name
    public const TBI_COUPON_NAME = "Reducere"; // Coupon name
    public const TBI_CALC_URL = self::TBI_PLATFORM_URL . "/calculator/"; // Calculator URL


    /**
     * Constructor
     *
     * @param Context $context Helper context
     */
    public function __construct(
        Context $context,
    ) {
        parent::__construct($context);
    }

    /**
     * Get configuration value based on path
     *
     * @param string $value Configuration path
     * @return mixed Configuration value
     */
    public function getConfigValue($value)
    {
        return $this->scopeConfig->getValue(
            $value,
            ScopeInterface::SCOPE_STORE
        );
    }

    /**
     * Get the store's secured base URL (HTTPS).
     *
     * @return string Secure base URL
     */
    public function getSecureStoreBaseUrl()
    {
        return $this->getConfigValue('web/secure/base_url');
    }

    /**
     * Static accessor for class constants based on name.
     *
     * @param string $constName The name of the constant.
     * @return mixed The value of the specified constant, or null if not found.
     */
    public static function getConstValue($constName)
    {
        // Check if the constant is defined in the current class and return its value, otherwise return null
        return defined('self::' . $constName) ? constant('self::' . $constName) : null;
    }

    /**
     * Check if product feature is enabled
     *
     * @return bool True if advertisement is enabled, false otherwise
     */
    public function isProductFeatureEnabled()
    {
        return 
            $this->getConfigValue('tbi_settings/general_settings/status') != 'Inactive' &&
            $this->getConfigValue('tbi_settings/product_page_settings/product_button') != 'button1';
    }

    /**
     * Get TBI bank logo URL
     *
     * @return string TBI bank logo URL
     */
    public function getTbiLogo()
    {
        return $this->getConstValue('TBI_CDN_URL') . $this->getConstValue('TBI_BANK_LOGO');
    }

    /**
     * Get logo URL based on selected option
     *
     * @param int $selectedOption Selected option
     * @return string Logo URL
     */
    public function getLogo($selectedOption)
    {
        return self::TBI_CDN_URL . self::TBI_BANK_LOGO_DARK;
    }

    public function getLabelData(){
        // Get dynamic tier count and build tier data dynamically
        $tierCount = $this->getConfigValue('tbi_settings/label_settings/tier_count') ?: 0;
        $tierData = [];

        for ($i = 1; $i <= $tierCount; $i++) {
            $tierData["tier{$i}"] = $this->getConfigValue("tbi_settings/label_settings/tier{$i}");
            $tierData["tier{$i}_period"] = $this->getConfigValue("tbi_settings/label_settings/tier{$i}_period");
            $tierData["tier{$i}_multiplier"] = $this->getConfigValue("tbi_settings/label_settings/tier{$i}_multiplier");
        }

        return array_merge([
            'minimumVisible' => $this->getConfigValue('tbi_settings/label_settings/minimum_visible'),
            'maximumVisible' => $this->getConfigValue('tbi_settings/label_settings/maximum_visible'),
            'standardMin' => $this->getConfigValue('tbi_settings/label_settings/standard_min'),
            'tierCount' => $tierCount,
            'bnplMin' => $this->getConfigValue('tbi_settings/label_settings/bnpl_min'),
            'bnplMax' => $this->getConfigValue('tbi_settings/label_settings/bnpl_max'),
            'bnplPeriod' => $this->getConfigValue('tbi_settings/label_settings/bnpl_period'),
            'bnplMultiplier' => $this->getConfigValue('tbi_settings/label_settings/bnpl_multiplier'),
            'bnplAnalysisFee' => $this->getConfigValue('tbi_settings/label_settings/bnpl_analysis_fee'),
            'standardAnalysisFee' => $this->getConfigValue('tbi_settings/label_settings/standard_analysis_fee'),
        ], $tierData);
    }

    public function getSelectedOption()
    {
        return $this->getConfigValue('tbi_settings/product_page_settings/product_button');
    }

    public function getData($price)
    {
        return $this->getSelectedOptionLabel(
            $this->getOptions($price),
            $this->getSelectedOption()
        );
    }

    private function calculateRoBnplInstallment(float $price, array $labelData): string
    {
        $analysisFee = (float) ($labelData['bnplAnalysisFee'] ?? 0);

        return number_format(($price + $analysisFee) / 4, 2, '.', '');
    }

    private function calculateRoStandardInstallment(float $price, array $labelData): string
    {
        $standardMin = (float) ($labelData['standardMin'] ?? 0);
        $tierCount = (int) ($labelData['tierCount'] ?? 0);

        if ($standardMin <= 0 || $price < $standardMin || $tierCount <= 0) {
            return '';
        }

        $multiplier = 0.0;
        $prevTierLimit = $standardMin;

        /*
         * Match Magento's existing Standard-only calculation:
         * choose the tier from the RAW product price.
         * The Standard analysis fee is added only after the tier/multiplier
         * has been selected.
         */
        for ($i = 1; $i <= $tierCount; $i++) {
            $currentTierLimit = (float) ($labelData["tier{$i}"] ?? 0);
            $currentMultiplier = (float) ($labelData["tier{$i}_multiplier"] ?? 0);

            $matchesLowerBound = $i === 1
                ? $price >= $prevTierLimit
                : $price > $prevTierLimit;

            if (
                $matchesLowerBound &&
                $currentTierLimit > 0 &&
                $price <= $currentTierLimit
            ) {
                $multiplier = $currentMultiplier;
                break;
            }

            if ($currentTierLimit > 0) {
                $prevTierLimit = $currentTierLimit;
            }
        }

        if ($multiplier <= 0) {
            return '';
        }

        $analysisFeeStd = (float) ($labelData['standardAnalysisFee'] ?? 0);

        return number_format(
            $multiplier * ($price + $analysisFeeStd),
            2,
            '.',
            ''
        );
    }

    private function getRoMode(
        float $price,
        array $labelData,
        string $standardInstallment
    ): string {
        $standardMin = (float) ($labelData['standardMin'] ?? 0);
        $bnplLimit = (float) ($labelData['bnplMax'] ?? 0);
        $hasStandard = is_numeric($standardInstallment);
        $hasBnpl = $bnplLimit > 0 && $price <= $bnplLimit;

        if (
            $hasStandard &&
            $hasBnpl &&
            $standardMin > 0 &&
            $price >= $standardMin
        ) {
            return 'dual';
        }

        if ($hasBnpl) {
            return 'bnpl';
        }

        return 'standard';
    }

    public function getOptions($price)
    {
        $price = (float) $price;
        $labelData = $this->getLabelData();

        if ($price > (float) $labelData['maximumVisible']) {
            return [];
        }

        $isInitiallyVisible =
            $price >= (float) $labelData['minimumVisible'];

        $standardInstallment = $this->calculateRoStandardInstallment(
            $price,
            $labelData
        );
        $bnplInstallment = $this->calculateRoBnplInstallment(
            $price,
            $labelData
        );
        $mode = $this->getRoMode(
            $price,
            $labelData,
            $standardInstallment
        );

        $standardTitleDual = (string) __('Pay as little as');
        $standardTitleSingle = (string) __('Pay as little as');
        $bnplTitleDual = (string) __('Fee-free 4 payments');
        $bnplTitleSingle = $bnplTitleDual;
        $currency = (string) __('RON');
        $monthLabel = (string) __('month');
        $monthSuffixDual = '/ ' . $monthLabel;
        $monthSuffixSingle = $monthSuffixDual;

        if ($mode === 'bnpl') {
            $initialTitle = $bnplTitleSingle;
            $initialAmount = $bnplInstallment;
        } else {
            // WC dual mode always starts from state A = standard.
            $initialTitle = $standardTitleSingle;
            $initialAmount = $standardInstallment;
        }

        $initialAmountText =
            number_format((float) $initialAmount, 2, '.', ',') .
            ' ' .
            $currency .
            ' ' .
            ($mode === 'dual' ? $monthSuffixDual : $monthSuffixSingle);

        $options = [
            [
                'value' => 'button',
                'label' => '<div id="tbi_button_container">' . __('No button') . '</div>',
            ],
        ];

        $selectedIndex = (int) substr($this->getSelectedOption(), -1);
        $legacyVariant = max(1, $selectedIndex - 1);

        $tierDataAttributes = '';

        for ($t = 1; $t <= $labelData['tierCount']; $t++) {
            $tierDataAttributes .=
                'data-t' . $t . '-limit="' .
                htmlspecialchars((string) $labelData["tier{$t}"], ENT_QUOTES, 'UTF-8') .
                '" ';
            $tierDataAttributes .=
                'data-t' . $t . '="' .
                htmlspecialchars((string) $labelData["tier{$t}_period"], ENT_QUOTES, 'UTF-8') .
                '" ';
            $tierDataAttributes .=
                'data-f' . $t . '="' .
                htmlspecialchars((string) $labelData["tier{$t}_multiplier"], ENT_QUOTES, 'UTF-8') .
                '" ';
        }

        // Keep the existing Magento button attributes for compatibility.
        $buttonHtml = '<div id="tbi_button_container1" class="tbi_button_container_ro">';
        $buttonHtml .=
            '<div id="tbi_button" ' .
            ($isInitiallyVisible ? '' : 'style="display:none" ') .
            'class="tbi_button' . $legacyVariant . ' tbi_button_ro" ' .
            'analysis-fee="' . htmlspecialchars((string) $labelData['bnplAnalysisFee'], ENT_QUOTES, 'UTF-8') . '" ' .
            'multiplier="' . htmlspecialchars((string) $labelData['bnplMultiplier'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-tier-count="' . (int) $labelData['tierCount'] . '" ' .
            'data-bnpl-analysis-fee="' . htmlspecialchars((string) $labelData['bnplAnalysisFee'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-standard-analysis-fee="' . htmlspecialchars((string) $labelData['standardAnalysisFee'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-hide-bnpl="' . htmlspecialchars((string) $labelData['bnplMax'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-period-bnpl="' . htmlspecialchars((string) $labelData['bnplPeriod'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-multiplier-bnpl="' . htmlspecialchars((string) $labelData['bnplMultiplier'], ENT_QUOTES, 'UTF-8') . '" ' .
            $tierDataAttributes .
            '>';

        // The WC animation reads state/config data from the BODY.
        // Magento now exposes the same attributes on its body node.
        $buttonHtml .=
            '<div id="tbi_button_body1" ' .
            'class="tbi_button_body' . $legacyVariant .
            ' tbi_button_body_ro tbi_button_body_ro--' . $mode . '" ' .
            'data-min-amount="' . htmlspecialchars((string) $labelData['minimumVisible'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-max-amount="' . htmlspecialchars((string) $labelData['maximumVisible'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-standard-min="' . htmlspecialchars((string) ($labelData['standardMin'] ?? 0), ENT_QUOTES, 'UTF-8') . '" ' .
            'data-hide-bnpl="' . htmlspecialchars((string) $labelData['bnplMax'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-bnpl-analysis-fee="' . htmlspecialchars((string) $labelData['bnplAnalysisFee'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-standard-analysis-fee="' . htmlspecialchars((string) $labelData['standardAnalysisFee'], ENT_QUOTES, 'UTF-8') . '" ' .
            'data-tier-count="' . (int) $labelData['tierCount'] . '" ' .
            'data-ro-mode="' . $mode . '" ' .
            'data-ro-dual-state="' . ($mode === 'dual' ? '1' : '0') . '" ' .
            'data-ro-standard-amount="' . htmlspecialchars($standardInstallment, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-bnpl-amount="' . htmlspecialchars($bnplInstallment, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-standard-title-dual="' . htmlspecialchars($standardTitleDual, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-standard-title-single="' . htmlspecialchars($standardTitleSingle, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-bnpl-title-dual="' . htmlspecialchars($bnplTitleDual, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-bnpl-title-single="' . htmlspecialchars($bnplTitleSingle, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-currency="' . htmlspecialchars($currency, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-month-suffix-dual="' . htmlspecialchars($monthSuffixDual, ENT_QUOTES, 'UTF-8') . '" ' .
            'data-ro-month-suffix-single="' . htmlspecialchars($monthSuffixSingle, ENT_QUOTES, 'UTF-8') . '" ' .
            $tierDataAttributes .
            '>';

        $buttonHtml .= '<div class="tbi_button_ro_info">';

        $buttonHtml .= '<div class="tbi_button_ro_brand">';
        $buttonHtml .=
            '<img src="' . $this->getLogo($selectedIndex) . '" ' .
            'id="tbi_button_logo1" ' .
            'class="tbi_button_ro_logo" ' .
            'alt="TBI Bank">';
        $buttonHtml .= '</div>';

        $buttonHtml .= '<div class="tbi_button_ro_divider" aria-hidden="true"></div>';

        // Exact WC state structure: viewport -> track -> current + next.
        $buttonHtml .= '<div class="tbi_button_ro_copy">';
        $buttonHtml .= '<div class="tbi_button_ro_state_viewport">';
        $buttonHtml .= '<div class="tbi_button_ro_state_track">';

        $buttonHtml .=
            '<div class="tbi_button_ro_state tbi_button_ro_state--current">';
        $buttonHtml .=
            '<div class="tbi_button_ro_title">' .
            htmlspecialchars($initialTitle, ENT_QUOTES, 'UTF-8') .
            '</div>';
        $buttonHtml .=
            '<div class="tbi_button_line--ro-amount">' .
            htmlspecialchars($initialAmountText, ENT_QUOTES, 'UTF-8') .
            '</div>';
        $buttonHtml .= '</div>';

        $buttonHtml .=
            '<div class="tbi_button_ro_state tbi_button_ro_state--next" aria-hidden="true">';
        $buttonHtml .= '<div class="tbi_button_ro_title"></div>';
        $buttonHtml .= '<div class="tbi_button_line--ro-amount"></div>';
        $buttonHtml .= '</div>';

        $buttonHtml .= '</div>'; // .tbi_button_ro_state_track
        $buttonHtml .= '</div>'; // .tbi_button_ro_state_viewport
        $buttonHtml .= '</div>'; // .tbi_button_ro_copy
        $buttonHtml .= '</div>'; // .tbi_button_ro_info

        $buttonHtml .=
            '<div class="tbi_button_ro_details">' .
            __('Details here') .
            '</div>';

        $buttonHtml .= '</div>';
        $buttonHtml .= '</div>';
        $buttonHtml .= '</div>';

        $options[] = [
            'value' => 'button' . $selectedIndex,
            'label' => $buttonHtml,
        ];

        return $options;
    }


    function getSelectedOptionLabel($options, $selectedOption) {
        foreach ($options as $option) {
            if ($option['value'] == $selectedOption) {
                return $option['label']; // Returns the HTML label of the matched option
            }
        }
        return null; // Return null if no match is found
    }
    
    /**
     * Base 64 encode 
     *
     * @param string $string
     * @return string
     */
    public function Encode($string) {
        if ($string === null || $string === '') {
            return '';
        } else {
            return base64_encode($string);
        }
    }
}
