<?php

namespace TbiBank\FusionPay\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Cache\TypeListInterface;
use Magento\Config\Model\ResourceModel\Config;
use TbiBank\FusionPay\Model\Cryptor;
use TbiBank\FusionPay\Helper\Data as FusionPayHelper;
use TbiBank\FusionPay\Logger\FusionPayLogger;

use Magento\Framework\Module\Manager;

/**
 * Observer for After Config Save actions.
 *
 * This observer is triggered after saving configuration in the Magento Admin for the FusionPay module.
 * It sends updated configuration data to an external API endpoint and updates the local config based on the response.
 */
class AfterConfigSave implements ObserverInterface
{
    /**
     * @var Curl
     */
    protected $curl;

    /**
     * @var Config
     */
    protected $config;

    /**
     * @var TypeListInterface
     */
    protected $cacheTypeList;

    /**
     * @var FusionPayHelper
     */
    protected $fusionPayHelper;

    /**
     * @var Cryptor
     */
    protected $cryptor;

    /**
     * @var FusionPayLogger
     */
    protected $logger; // Custom Logger

    /**
     * Endpoints for the external API.
     *
     * @var string
     * @var string
     */
    protected $tbiEndpoint;
    protected $tbiEndpointStatus;



    protected $moduleManager; 



    /**
     * Constructor.
     *
     * @param Curl $curl
     * @param Config $config
     * @param TypeListInterface $cacheTypeList
     * @param FusionPayHelper $fusionPayHelper
     * @param Cryptor $cryptor
     * @param FusionPayLogger $logger Custom Logger
     */
    public function __construct(
        Curl $curl,
        Config $config,
        TypeListInterface $cacheTypeList,
        FusionPayHelper $fusionPayHelper,
        Cryptor $cryptor,
        FusionPayLogger $logger, // Inject the custom Logger
        Manager $moduleManager
    ) {
        $this->curl = $curl;
        $this->config = $config;
        $this->cacheTypeList = $cacheTypeList;
        $this->fusionPayHelper = $fusionPayHelper;
        $this->cryptor = $cryptor;
        $this->logger = $logger; // Initialize the custom Logger
        $this->tbiEndpoint = $this->fusionPayHelper->getConstValue('TBI_PLATFORM_URL') . '/api/PluginsSettings';
        $this->tbiEndpointStatus = $this->fusionPayHelper->getConstValue('TBI_PLATFORM_URL') . '/api/PluginsSettings/status';
        $this->moduleManager = $moduleManager;
    }

    /**
     * Executes the observer action.
     *
     * @param Observer $observer
     */
    public function execute(Observer $observer)
    {
        try {
            // Fetch encryption key and period settings from the module's configuration
            $encryptionKey = $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/encryption_key');

            $apiData = [
                'reseller_code' => $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_code'),
                'reseller_key'  => $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_key'),
                'plugin'        => 'MagentoSettings'
            ];

            // Send data to the external API
            $jsonData = json_encode($apiData);

            $this->curl->post($this->tbiEndpoint, $jsonData);
            $this->curl->setOption(CURLOPT_RETURNTRANSFER, true);

            // Handle cURL response
            if ($this->curl->getStatus() >= 200 && $this->curl->getStatus() < 300) {
                
                $response = $this->curl->getBody();
                $responseData = json_decode($response, true);
    
                if($responseData['error'] != 0) {
                    
                    $this->logger->info('Problem with API call to ' . $this->tbiEndpoint . ' response: ' . preg_replace('/\s+/', '',$response));
                    $this->updateConfigStatus('Inactive');

                    return;
                }

                // Set tbi limits
                $new_responseData = $this->setTbiLimits($responseData, $apiData);

                // Update local configuration based on the API response
                $this->updateConfigStatus('Active');                
                $this->updateLocalConfig($new_responseData);

                $this->sendNotification();
                
                $this->logger->info('Successful API call to ' . $this->tbiEndpoint . ' response: ' . preg_replace('/\s+/', '',$response));

            } else {
                $this->updateConfigStatus('Inactive');

                $this->logger->error('Here is the invalid to ' . $this->tbiEndpoint . '. Status: ' . $this->curl->getStatus());
                return;
            }

        } catch (\Exception $e) {
            // Log the exception
            $this->logger->error('Exception in AfterConfigSave: ' . $e->getMessage());
        } finally {
            $this->cacheTypeList->cleanType(\Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER);
        }

    }

    /**
     * Set tbi minimum and maximum limits
    */
    protected function setTbiLimits($responseData, array $apiData = []) {

        $bnplMin = isset($responseData['bnpl_min']) ? (float)$responseData['bnpl_min'] : 0.0;

        // Keep the Standard lower bound separate from the overall BNPL-visible minimum.
        // This value is used only to decide when both RO offers are valid/animated.
        $standardMin = 0.0;

        if (isset($responseData['tier1_min']) && is_numeric($responseData['tier1_min'])) {
            $standardMin = (float)$responseData['tier1_min'];
        } elseif (isset($responseData['minimumVisible']) && is_numeric($responseData['minimumVisible'])) {
            $standardMin = (float)$responseData['minimumVisible'];
        }

        if ($standardMin > 0) {
            $responseData['standardMin'] = $standardMin;
        }

        // The maximum allowed visible value should be the last max tier from the API.
        $maxTierLimit = $bnplMin;

        if (isset($responseData['tiers']) && is_array($responseData['tiers']) && !empty($responseData['tiers'])) {
            $tiers = array_values($responseData['tiers']);
            $maxTierLimit = (float)end($tiers);
        }

        if ($maxTierLimit < $bnplMin) {
            $maxTierLimit = $bnplMin;
        }

        $currentResellerCode = (string)($apiData['reseller_code'] ?? $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_code'));
        $currentResellerKey = (string)($apiData['reseller_key'] ?? $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_key'));

        $lastApiResellerCode = (string)$this->fusionPayHelper->getConfigValue('tbi_settings/label_settings/last_api_reseller_code');
        $lastApiResellerKey = (string)$this->fusionPayHelper->getConfigValue('tbi_settings/label_settings/last_api_reseller_key');

        $credentialsChanged = (
            $currentResellerCode !== $lastApiResellerCode
            || $currentResellerKey !== $lastApiResellerKey
        );

        // First save / changed credentials: initialize visible limits directly from the API response.
        if ($credentialsChanged) {
            $responseData['minimumVisible'] = $bnplMin;
            $responseData['maximumVisible'] = $maxTierLimit;
        } else {
            $minimumVisible = (float)$this->fusionPayHelper->getConfigValue('tbi_settings/label_settings/minimum_visible');
            $maximumVisible = (float)$this->fusionPayHelper->getConfigValue('tbi_settings/label_settings/maximum_visible');

            if ($minimumVisible <= 0) {
                $minimumVisible = $bnplMin;
            }

            if ($maximumVisible <= 0) {
                $maximumVisible = $maxTierLimit;
            }

            // Later manual edits: clamp values inside the API allowed range.
            $minimumVisible = max($bnplMin, min($maxTierLimit, $minimumVisible));
            $maximumVisible = max($bnplMin, min($maxTierLimit, $maximumVisible));

            if ($maximumVisible < $minimumVisible) {
                $maximumVisible = $minimumVisible;
            }

            $responseData['minimumVisible'] = $minimumVisible;
            $responseData['maximumVisible'] = $maximumVisible;
        }

        $responseData['last_api_reseller_code'] = $currentResellerCode;
        $responseData['last_api_reseller_key'] = $currentResellerKey;

        return $responseData;
    }


    /**
     * Saves a given value to the specified configuration path.
     *
     * @param string $key Configuration path
     * @param mixed $value Value to be saved
     */
    protected function saveConfigValue($key, $value) {
        $this->config->saveConfig($key, $value, 'default', 0);
    }

    /**
     * Updates the module's activation status in the configuration.
     *
     * @param string $status New status value ('Active' or 'Inactive')
     */
    protected function updateConfigStatus($status) {
        $this->saveConfigValue('tbi_settings/general_settings/status', $status);
    }

    /**
     * Updates local configuration settings based on the API response.
     *
     * @param array $responseData Data received from the API
     */
    protected function updateLocalConfig($responseData) {

        // Handle dynamic tiers
        
        // Clear existing tier data first
        $existingTierCount = $this->fusionPayHelper->getConfigValue('tbi_settings/label_settings/tier_count') ?: 0;
        for ($i = 1; $i <= $existingTierCount; $i++) {
            $this->saveConfigValue("tbi_settings/label_settings/tier{$i}", null);
            $this->saveConfigValue("tbi_settings/label_settings/tier{$i}_period", null);
            $this->saveConfigValue("tbi_settings/label_settings/tier{$i}_multiplier", null);
        }
        
        // Handle dynamic tiers from API response - fully dynamic approach
        if (isset($responseData['tiers']) && isset($responseData['periods']) && isset($responseData['multipliers'])) {
            $tierCount = count($responseData['tiers']);
            $this->saveConfigValue('tbi_settings/label_settings/tier_count', $tierCount);
            
            for ($i = 0; $i < $tierCount; $i++) {
                $tierIndex = $i + 1;
                $this->saveConfigValue("tbi_settings/label_settings/tier{$tierIndex}", $responseData['tiers'][$i]);
                $this->saveConfigValue("tbi_settings/label_settings/tier{$tierIndex}_period", $responseData['periods'][$i]);
                $this->saveConfigValue("tbi_settings/label_settings/tier{$tierIndex}_multiplier", $responseData['multipliers'][$i]);
            }
        } else {
            // If no dynamic tier data, set tier count to 0
            $this->saveConfigValue('tbi_settings/label_settings/tier_count', 0);
        }

        // Mapping between API response and local config paths for other fields
        $configMappings = [
            'minimum_visible' => 'minimumVisible',
            'maximum_visible' => 'maximumVisible',
            'standard_min' => 'standardMin',
            'bnpl_min' => 'bnpl_min',
            'bnpl_max' => 'bnpl_max',
            'bnpl_period' => 'bnpl_period',
            'bnpl_multiplier' => 'bnpl_multiplier',
            'bnpl_analysis_fee' => 'bnpl_analysis_fee',
            'standard_analysis_fee' => 'standard_analysis_fee'
        ];

        foreach ($configMappings as $localKey => $apiKey) {
            if (isset($responseData[$apiKey])) {
                $this->saveConfigValue("tbi_settings/label_settings/{$localKey}", $responseData[$apiKey]);
            }
        }

        if (isset($responseData['last_api_reseller_code'])) {
            $this->saveConfigValue('tbi_settings/label_settings/last_api_reseller_code', $responseData['last_api_reseller_code']);
        }

        if (isset($responseData['last_api_reseller_key'])) {
            $this->saveConfigValue('tbi_settings/label_settings/last_api_reseller_key', $responseData['last_api_reseller_key']);
        }
    }

    /**
     * Sends a notification to the TBI endpoint about the status of the plugin.
     *
     * This function is used to send a notification to the TBI endpoint about the
     * status of the plugin.
     *
     * @return void
    */
    protected function sendNotification() {

        $moduleName = 'TbiBank_FusionPay';
        // Flush Cache Before Checking Status
        $this->cacheTypeList->cleanType(\Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER);
        
        // Get Correct Module Status
        $status = $this->moduleManager->isEnabled($moduleName) ? 'active' : 'inactive';

        $apiData = [
            'reseller_code' => $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_code'),
            'reseller_key'  => $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_key'),
            'plugin'        => 'Magento2',
            'version'       => '1.5',
            'status'        => $status,
            'date'          => date('Y-m-d H:i:s')
        ];

        // Send data to the external API
        $jsonData = json_encode($apiData);
        $this->logger->error('Send notification to ' . $this->tbiEndpointStatus . '. Data: ' . $jsonData);

        $this->logger->error('Send notification response: ' . $this->curl->post($this->tbiEndpointStatus, $jsonData));
    }



}
