<?php

namespace Oney\ThreeByFour\Helper;

use Magento\Backend\App\Area\FrontNameResolver;
use Magento\Directory\Model\CountryFactory;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Sales\Model\Order\InvoiceRepository;
use Magento\Store\Model\ScopeInterface;
use Magento\Framework\App\State;
use Magento\Framework\Locale\Resolver;
use Magento\Sales\Model\OrderRepository;

/**
 * Configuration Helper
 * 
 * Central configuration helper for Oney ThreeByFour module.
 * Handles all configuration values, API settings, and utility functions.
 * 
 * @package Oney\ThreeByFour\Helper
 * @version 1.0.0
 * @author Oney
 * @since 1.0.0
 */
class Config extends AbstractHelper
{
    /**
     * XML path constants for configuration
     * 
     * @const string
     * @version 1.0.0
     */
    const XML_PATH_THREEBYFOUR = "threebyfour/";
    const XML_PATH_LEGAL_CREDIT_INTERMEDIARY = "threebyfour/legal/credit_intermediary";
    const XML_PATH_LEGAL_COMPANY_NAME = "threebyfour/legal/company_name";
    const XML_PATH_LEGAL_DOCUMENT = "threebyfour/legal/document";
    const XML_PATH_FR_SPECIFICS = "threebyfour/fr_specifics/";
    const URL_PATH_DOCUMENT = "oney/";
    const URL_ONEY_INFO = "https://www.oney.pt/3x-4x-oney";

    /**
     * Country phone prefixes
     * 
     * @var array
     * @version 1.0.0
     */
    private $_prefix = ["FR" => "33", "ES" => "34"];
    
    /**
     * Application state instance
     * 
     * @var State
     * @version 1.0.0
     */
    protected $_state;
    
    /**
     * Locale resolver instance
     * 
     * @var Resolver
     * @version 1.0.0
     */
    protected $_locale;
    
    /**
     * Order repository instance
     * 
     * @var OrderRepository
     * @version 1.0.0
     */
    protected $orderRepository;
    
    /**
     * Invoice repository instance
     * 
     * @var InvoiceRepository
     * @version 1.0.0
     */
    protected $invoiceRepository;

    /**
     * @var CountryFactory
     */
    protected $countryFactory;

    /**
     * Constructor
     * 
     * @param Context $context Helper context
     * @param State $state Application state
     * @param Resolver $locale Locale resolver
     * @param OrderRepository $orderRepository Order repository
     * @param InvoiceRepository $invoiceRepository Invoice repository
     * @param CountryFactory $countryFactory Country factory
     * @version 1.0.0
     */
    public function __construct(
        Context $context,
        State $state,
        Resolver $locale,
        OrderRepository $orderRepository,
        InvoiceRepository $invoiceRepository,
        CountryFactory $countryFactory
    ) {
        $this->_state = $state;
        $this->_locale = $locale;
        $this->orderRepository = $orderRepository;
        $this->invoiceRepository = $invoiceRepository;
        $this->countryFactory = $countryFactory;
        parent::__construct($context);
    }

    /**
     * Get phone prefix by country
     * 
     * Returns the phone prefix for a specific country.
     * 
     * @param string $country Country code
     * @return string|null Phone prefix
     * @version 1.0.0
     */
    public function getPhonePrefixByCountry(string $country): ?string
    {
        return $this->_prefix[$country] ?? null;
    }

    /**
     * Get language code
     * 
     * Returns the current language code from locale.
     * 
     * @return string Language code
     * @version 1.0.0
     */
    public function getLanguageCode(): string
    {
        return strtoupper(explode("_", $this->_locale->getLocale())[0]);
    }

    /**
     * Get configuration value
     * 
     * Retrieves configuration value with store context handling.
     * 
     * @param string $field Configuration field path
     * @param int|string|null $store Store ID
     * @return string|null Configuration value
     * @version 1.0.0
     */
    public function getConfigValue(string $field, $store = null): ?string
    {
        if ($this->_state != null && $this->_state->getAreaCode() === FrontNameResolver::AREA_CODE) {
            $store = 0;

            preg_match("/\/store\/\d*\//",$this->_getRequest()->getPathInfo(), $match);
            if($match) {
                $store = str_replace(['store','/'],"", $match[0]);
            }

            preg_match("/\/order_id\/\d*\//",$this->_getRequest()->getPathInfo(), $match2);
            if($match2) {
                $store = $this->orderRepository->get(str_replace(['order_id','/'],"",$match2[0]))->getStoreId();
            }

            preg_match("/\/invoice_id\/\d*\//",$this->_getRequest()->getPathInfo(), $match3);
            if($match3) {
                $store = $this->invoiceRepository->get(str_replace(['invoice_id','/'],"",$match3[0]))->getStoreId();
            }
        }
        return $this->scopeConfig->getValue($field,
            ScopeInterface::SCOPE_STORE,
            $store);
    }


    /**
     * Get URL for step
     * 
     * Builds API URL for specific step based on environment configuration.
     * 
     * @param string $field Step field name
     * @param int|string|null $store Store ID
     * @return string|null Complete API URL
     * @version 1.0.0
     */
    public function getUrlForStep(string $field = '', $store = null): ?string
    {
        $preprod = $this->getGeneralConfigValue('environnement', $store);
        if ($preprod) {
            $base = $this->getGeneralConfigValue('url_api_prod', $store);
        }
        else {
            $base = $this->getGeneralConfigValue('url_api_preprod', $store);
        }
        $route = $this->getConfigValue(self::XML_PATH_THREEBYFOUR . 'general/routes/' . $field, $store);
        return $base . $route;
    }

    /**
     * Get API configuration value
     * 
     * Retrieves API-specific configuration value.
     * 
     * @param string $field API field name
     * @param int|string|null $store Store ID
     * @return string|null Configuration value
     * @version 1.0.0
     */
    public function getApiConfigValue(string $field, $store = null): ?string
    {
        return $this->getConfigValue(self::XML_PATH_THREEBYFOUR . 'api/' . $field, $store);
    }

    /**
     * Get general configuration value
     * 
     * Retrieves general configuration value.
     * 
     * @param string $field General field name
     * @param int|string|null $store Store ID
     * @return string|null Configuration value
     * @version 1.0.0
     */
    public function getGeneralConfigValue(string $field, $store = null): ?string
    {
        return $this->getConfigValue(self::XML_PATH_THREEBYFOUR . 'general/' . $field, $store);
    }

    /**
     * Get carrier configuration
     * 
     * Retrieves carrier-specific configuration value.
     * 
     * @param string $shippingMethod Shipping method code
     * @param string $field Configuration field
     * @param int|string|null $store Store ID
     * @return string|int Configuration value or default 1
     * @version 1.0.0
     */
    public function getCarrierConfig(string $shippingMethod = "", string $field = "", $store = null)
    {
        $configValue = $this->getConfigValue('carriers/' . $shippingMethod . "/" . $field, $store);
        if ($configValue) {
            return $configValue;
        } else {
            return 1;
        }
    }

    /**
     * Get secret configuration
     * 
     * Retrieves API secret configuration value.
     * 
     * @param int|string|null $store Store ID
     * @return string Secret value or "None"
     * @version 1.0.0
     */
    public function getSecret($store = null): string
    {
        $secret = $this->getConfigValue(self::XML_PATH_THREEBYFOUR . 'api/secret', $store);
        return is_null($secret) ? "None" : $secret;
    }

    /**
     * Check if payment is active for code
     * 
     * Checks if a specific payment method is active.
     * 
     * @param string $method Payment method code
     * @param int|string|null $store Store ID
     * @return bool True if active
     * @version 1.0.0
     */
    public function isPaymentActiveForCode(string $method, $store = null): bool
    {
        return (bool)$this->getConfigValue('payment/oney_section/' . $method, $store);
    }

    /**
     * Check if phone number is correct
     * 
     * Validates phone number format against country specifications.
     * 
     * @param string|null $getTelephone Phone number to validate
     * @return bool True if valid
     * @version 1.0.0
     */
    public function isCorrectPhone(?string $getTelephone): bool
    {
        preg_match(
            $this->getCountrySpecificationsConfigValue('phone'),
            $getTelephone,
            $matches
        );
        return !empty($matches);
    }

    /**
     * Get country specifications configuration value
     * 
     * Retrieves country-specific configuration value.
     * 
     * @param string $field Configuration field
     * @param int|string|null $store Store ID
     * @return string|null Configuration value
     * @version 1.0.0
     */
    public function getCountrySpecificationsConfigValue(string $field, $store = null): ?string
    {
        return $this->getConfigValue(self::XML_PATH_THREEBYFOUR .
            "country_specifications/" .
            $this->getConfigValue("general/country/default", $store) . "/" . $field,
        $store);
    }

    /**
     * Check if credit intermediary is enabled
     * 
     * Checks if credit intermediary legal text is enabled.
     * 
     * @param int|string|null $store Store ID
     * @return bool True if enabled
     * @version 1.0.0
     */
    public function isCreditIntermediary($store = null): bool
    {
        return (bool)$this->getConfigValue(self::XML_PATH_LEGAL_CREDIT_INTERMEDIARY, $store);
    }

    /**
     * Get company name from Oney config
     * 
     * Retrieves the company name for legal display.
     * 
     * @param int|string|null $store Store ID
     * @return string|null Company name
     * @version 1.0.0
     */
    public function getCompanyName($store = null): ?string
    {
        return $this->getConfigValue(self::XML_PATH_LEGAL_COMPANY_NAME, $store);
    }

    /**
     * Get Oney PDF from Oney config
     * 
     * Retrieves the Oney PDF document URL if configured.
     * 
     * @param int|string|null $store Store ID
     * @return string|null PDF URL or null
     * @version 1.0.0
     */
    public function getOneyPdf($store = null): ?string
    {
        if($this->getConfigValue(self::XML_PATH_LEGAL_DOCUMENT, $store)) {
            return self::URL_PATH_DOCUMENT . $this->getConfigValue(self::XML_PATH_LEGAL_DOCUMENT, $store);
        }
        return null;
    }

    /**
     * Check if legal is enabled
     * 
     * Checks if legal text display is enabled for the country.
     * 
     * @param int|string|null $store Store ID
     * @return bool True if enabled
     * @version 1.0.0
     */
    public function isLegalEnabled($store = null): bool
    {
        return (bool)$this->getCountrySpecificationsConfigValue("legal_enabled", $store);
    }

    /**
     * Check if secure is enabled
     * 
     * Checks if secure payment is enabled for the country.
     * 
     * @param int|string|null $store Store ID
     * @return bool True if enabled
     * @version 1.0.0
     */
    public function hasSecure($store = null): bool
    {
        return (bool)$this->getCountrySpecificationsConfigValue("has_secure", $store);
    }

    /**
     * Add country code translation
     * 
     * Handles language translations for a specific country.
     * 
     * @param int|string|null $store Store ID
     * @return string Country code suffix
     * @version 1.0.0
     */
    public function addCountryCodeTranslation($store = null): string
    {
        $countryCode = '';
        if ($this->getCountrySpecificationsConfigValue("add_country_code_translation", $store)) {
            $countryCode = ' _'.strtolower($this->getConfigValue("general/country/default"));
        }
        return $countryCode;
    }

    /**
     * @param int|string|null $store
     * @return bool
     */
    public function isFranceScope($store = null): bool
    {
        return strtoupper((string)$this->getConfigValue('general/country/default', $store)) === 'FR';
    }

    /**
     * @param int|string|null $store
     * @return string|null
     */
    public function getMerchantOriasNumber($store = null): ?string
    {
        return $this->getConfigValue(self::XML_PATH_FR_SPECIFICS . 'merchant_orias_number', $store);
    }

    /**
     * @param int|string|null $store
     * @return string|null
     */
    public function getMerchantNameFromStoreConfig($store = null): ?string
    {
        return $this->getConfigValue('general/store_information/name', $store);
    }

    /**
     * @param int|string|null $store
     * @return string
     */
    public function getMerchantAddressFromStoreConfig($store = null): string
    {
        $countryCode = (string)$this->getConfigValue('general/store_information/country_id', $store);
        $countryName = '';
        if (!empty($countryCode)) {
            try {
                $countryName = (string)$this->countryFactory->create()->loadByCode($countryCode)->getName();
            } catch (\Exception $e) {
                $countryName = $countryCode;
            }
        }

        $parts = array_filter([
            $this->getConfigValue('general/store_information/street_line1', $store),
            $this->getConfigValue('general/store_information/street_line2', $store),
            trim((string)$this->getConfigValue('general/store_information/postcode', $store) . ' ' . (string)$this->getConfigValue('general/store_information/city', $store)),
            $countryName
        ]);

        return implode(', ', $parts);
    }

    /**
     * @param int|string|null $store
     * @return array
     */
    public function getFranceWidgetOptions($store = null): array
    {
        if (!$this->isFranceScope($store)) {
            return [];
        }

        $response = [
            'merchant_name' => (string)$this->getMerchantNameFromStoreConfig($store),
            'merchant_orias_number' => (string)$this->getMerchantOriasNumber($store),
            'merchant_address' => (string)$this->getMerchantAddressFromStoreConfig($store)
        ];

        return array_filter($response, static function ($value) {
            return trim((string)$value) !== '';
        });
    }

    /**
     * Get merchant GUID
     * 
     * Retrieves the merchant GUID configuration value.
     * 
     * @param int|string|null $store Store ID
     * @return string|null Merchant GUID
     * @version 1.0.0
     */
    public function getMerchantGuid($store = null): ?string
    {
        return $this->getConfigValue(self::XML_PATH_THREEBYFOUR . 'general/merchant_guid', $store);
    }
}
