<?php

declare(strict_types=1);

namespace CloudXM\NFe\Admin\Pages;

use CloudXM\NFe\Admin\HasTemplate;
use CloudXM\NFe\Config\Configuration;
use CloudXM\NFe\Services\ApiClient;
use CloudXM\NFe\Services\TenantConfigCache;
use CloudXM\SDK\Support\HasLogger;

/**
 * NFe Settings Page
 *
 * Displays plugin settings with tenant defaults from NFE server
 */
class SettingsPage
{
    use HasTemplate;

    private const TENANT_DEFAULTS_CACHE_KEY = 'cloudxm_nfe_tenant_defaults';
    private const TENANT_DEFAULTS_CACHE_TTL = 300;
    private const COMPANIES_CACHE_KEY = 'cloudxm_nfe_companies';
    private const COMPANIES_CACHE_TTL = 300;
    private const COMPANY_CONFIG_CACHE_KEY = 'cloudxm_nfe_company_config_';
    private const COMPANY_CONFIG_CACHE_TTL = 300;

    private ?array $tenantDefaults = null;
    private array $companies = [];
    private ?array $companyConfig = null;
    private string $errorMessage = '';
    private string $successMessage = '';

    public function __construct(
        private Configuration $config,
        private ApiClient $apiClient,
        private TenantConfigCache $tenantConfigCache
    ) {
        add_action('admin_post_cloudxm_nfe_save_settings', [$this, 'handleSave']);
        add_action('wp_ajax_cloudxm_nfe_test_connection', [$this, 'handleTestConnection']);
        add_action('admin_enqueue_scripts', [$this, 'enqueueAdminAssets']);
    }

    /**
     * Enqueue admin assets
     */
    public function enqueueAdminAssets(): void
    {
        if (isset($_GET['page']) && $_GET['page'] === 'cloudxm-nfe-settings') {
            wp_enqueue_style(
                'cloudxm-nfe-admin-settings',
                CLOUDXM_NFE_URL . 'assets/css/admin-settings.css',
                [],
                CLOUDXM_NFE_VERSION
            );

            wp_enqueue_script(
                'cloudxm-nfe-settings',
                CLOUDXM_NFE_URL . 'assets/js/settings.js',
                ['jquery'],
                CLOUDXM_NFE_VERSION,
                true
            );
            wp_localize_script('cloudxm-nfe-settings', 'cloudxm_nfe_settings', [
                'ajax_url' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce('cloudxm_nfe_test_connection'),
                'settings_nonce' => wp_create_nonce('cloudxm_nfe_settings'),
                'i18n' => [
                    'testing' => __('Testing connection...', 'woocommerce-cloudxm-nfe'),
                    'success' => __('Connection successful!', 'woocommerce-cloudxm-nfe'),
                    'error' => __('Connection failed. Check your API URL and token.', 'woocommerce-cloudxm-nfe'),
                    'error_detail' => __('Error:', 'woocommerce-cloudxm-nfe'),
                    'municipality_code' => __('Municipality Code', 'woocommerce-cloudxm-nfe'),
                    'municipal_service_code' => __('Municipal Service Code', 'woocommerce-cloudxm-nfe'),
                    'national_service_code' => __('National Service Code', 'woocommerce-cloudxm-nfe'),
                ],
            ]);
        }
    }

    /**
     * Handle test connection AJAX request
     */
    public function handleTestConnection(): void
    {
        check_ajax_referer('cloudxm_nfe_test_connection', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Unauthorized', 'woocommerce-cloudxm-nfe')]);
            return;
        }

        $environment = $this->config->get('environment');
        $apiBaseUrl = $this->config->getApiBaseUrl();
        $apiToken = $this->config->getApiToken();

        $this->log()->info('nfe.settings.test_connection', [
            'environment' => $environment,
            'api_base_url' => $apiBaseUrl,
            'has_token' => !empty($apiToken),
        ]);

        if (empty($apiToken)) {
            wp_send_json_error([
                'message' => __('API token is empty. Please configure it first.', 'woocommerce-cloudxm-nfe')
            ]);
            return;
        }

        try {
            // Refresh the tenant config cache so emission picks up latest server settings
            $tenantConfig = $this->tenantConfigCache->refresh();
            wp_send_json_success([
                'message' => sprintf(
                    __('Connection successful! Account ID: %s, Environment: %s', 'woocommerce-cloudxm-nfe'),
                    $tenantConfig->tenant_id,
                    $environment
                ),
                'tenant_id' => $tenantConfig->tenant_id,
                'municipality_code' => $tenantConfig->nfse->municipality_code,
                'municipal_service_code' => $tenantConfig->nfse->municipal_service_code,
                'national_service_code' => $tenantConfig->nfse->national_service_code,
            ]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.settings.test_connection_failed', [
                'error' => $e->getMessage(),
            ]);
            wp_send_json_error([
                'message' => __('Connection failed. Check your API URL and token.', 'woocommerce-cloudxm-nfe'),
                'error_detail' => $e->getMessage(),
            ]);
        }
    }

    /**
     * Render the settings page
     */
    public function render(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(__('You do not have sufficient permissions to access this page.', 'woocommerce-cloudxm-nfe'));
        }

        if (isset($_GET['settings-updated'])) {
            $this->successMessage = __('Settings saved successfully.', 'woocommerce-cloudxm-nfe');
        }
        if (isset($_GET['settings-error'])) {
            $this->errorMessage = __('Failed to save settings. Please review the form values and try again.', 'woocommerce-cloudxm-nfe');
        }

        $this->fetchTenantDefaults();
        $this->fetchCompanies();
        $this->fetchCompanyConfig();

        $settings = $this->getSettingsWithDefaults();

        $data = [
            'page_title' => __('CloudXM NFe Settings', 'woocommerce-cloudxm-nfe'),
            'nonce' => wp_create_nonce('cloudxm_nfe_settings'),
            'action_url' => admin_url('admin-post.php'),
            'settings' => $settings,
            'tenant_defaults' => $this->tenantDefaults,
            'companies' => $this->companies,
            'company_config' => $this->companyConfig,
            'error_message' => $this->errorMessage,
            'success_message' => $this->successMessage,
            'has_api_connection' => $this->tenantDefaults !== null,
        ];

        $this->loadTemplate('admin/pages/settings', $data);
    }

    /**
     * Handle settings save
     */
    public function handleSave(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(__('Unauthorized access', 'woocommerce-cloudxm-nfe'));
        }

        if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'cloudxm_nfe_settings')) {
            wp_die(__('Security check failed', 'woocommerce-cloudxm-nfe'));
        }

        try {
            $currentSettings = $this->getSettingsWithDefaults();

            $environmentRaw = $this->postValue('cloudxm_nfe_environment', 'environment', 'sandbox');
            $environment = $this->normalizeEnvironment((string) $environmentRaw);

            if (!in_array($environment, ['sandbox', 'production', 'staging', 'custom'], true)) {
                throw new \InvalidArgumentException(__('Invalid environment selected', 'woocommerce-cloudxm-nfe'));
            }

            $apiBaseUrlInput = trim((string) $this->postValue('cloudxm_nfe_api_base_url', 'api_base_url', ''));
            if ($apiBaseUrlInput === '') {
                $apiBaseUrl = $this->getDefaultApiBaseUrl($environment);
            } else {
                $apiBaseUrl = $this->normalizeApiBaseUrl($apiBaseUrlInput);
            }

            $cancelDaysRaw = trim((string) $this->postValue('cloudxm_nfe_cancel_days_limit', 'cancel_days_limit', (string) ($currentSettings['cancel_days_limit'] ?? '5')));
            $cancelDaysLimit = absint($cancelDaysRaw);
            if ($cancelDaysLimit > 365) {
                throw new \InvalidArgumentException(__('Cancellation days limit must be between 0 and 365', 'woocommerce-cloudxm-nfe'));
            }

            $tokenSandboxInput = trim((string) $this->postValue('cloudxm_nfe_token_sandbox', 'token_sandbox', ''));
            $tokenProductionInput = trim((string) $this->postValue('cloudxm_nfe_token_production', 'token_production', ''));
            $tokenStagingInput = trim((string) $this->postValue('cloudxm_nfe_token_staging', 'token_staging', ''));
            $tokenCustomInput = trim((string) $this->postValue('cloudxm_nfe_token_custom', 'token_custom', ''));

            $tokenSandbox = $tokenSandboxInput === ''
                ? (string) ($currentSettings['token_sandbox'] ?? '')
                : sanitize_text_field($tokenSandboxInput);

            $tokenProduction = $tokenProductionInput === ''
                ? (string) ($currentSettings['token_production'] ?? '')
                : sanitize_text_field($tokenProductionInput);

            $tokenStaging = $tokenStagingInput === ''
                ? (string) ($currentSettings['token_staging'] ?? '')
                : sanitize_text_field($tokenStagingInput);

            $tokenCustom = $tokenCustomInput === ''
                ? (string) ($currentSettings['token_custom'] ?? '')
                : sanitize_text_field($tokenCustomInput);

            $municipalityCodeInput = trim((string) $this->postValue('cloudxm_nfe_municipality_code', 'municipality_code', ''));
            if ($municipalityCodeInput === '') {
                $municipalityCode = (string) ($currentSettings['municipality_code'] ?? '');
                if ($municipalityCode === '') {
                    // Keep empty - will use tenant default at runtime
                    $municipalityCode = '';
                }
            } else {
                $municipalityCode = sanitize_text_field($municipalityCodeInput);
                if (!preg_match('/^\d{7}$/', $municipalityCode)) {
                    throw new \InvalidArgumentException(__('Municipality code must be 7 digits', 'woocommerce-cloudxm-nfe'));
                }
            }

            // Backward compatibility for old "api_token" field.
            $apiTokenFallback = sanitize_text_field((string) $this->postValue('api_token', 'api_token', ''));
            if ($apiTokenFallback !== '') {
                if ($environment === 'production' && $tokenProduction === '') {
                    $tokenProduction = $apiTokenFallback;
                }
                if ($environment === 'sandbox' && $tokenSandbox === '') {
                    $tokenSandbox = $apiTokenFallback;
                }
                if ($environment === 'staging' && $tokenStaging === '') {
                    $tokenStaging = $apiTokenFallback;
                }
                if ($environment === 'custom' && $tokenCustom === '') {
                    $tokenCustom = $apiTokenFallback;
                }
            }

            $selectedCompanyCnpj = '';
            $companyInput = trim((string) $this->postValue('cloudxm_nfe_selected_company_cnpj', 'selected_company_cnpj', ''));
            if ($companyInput !== '') {
                $selectedCompanyCnpj = preg_replace('/[^0-9]/', '', $companyInput);
            }

            $autoIssueStatus = sanitize_text_field((string) $this->postValue('cloudxm_nfe_auto_issue_status', 'auto_issue_status', 'manual'));

            $settings = [
                'api_base_url' => $apiBaseUrl,
                'environment' => $environment,
                'token_sandbox' => $tokenSandbox,
                'token_production' => $tokenProduction,
                'token_staging' => $tokenStaging,
                'token_custom' => $tokenCustom,
                'api_token' => match ($environment) {
                    'production' => $tokenProduction,
                    'staging' => $tokenStaging,
                    'custom' => $tokenCustom,
                    default => $tokenSandbox,
                },
                'selected_company_cnpj' => $selectedCompanyCnpj,
                'cancel_days_limit' => $cancelDaysLimit,
                'auto_issue' => $autoIssueStatus !== 'manual' ? '1' : '0',
                'auto_issue_status' => $autoIssueStatus,
                'auto_cancel_status' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_auto_cancel_status', 'auto_cancel_status', 'disabled')),
                'enable_custom_description' => isset($_POST['cloudxm_nfe_enable_custom_description']) ? '1' : '0',
                'municipal_service_code' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_municipal_service_code', 'municipal_service_code', '')),
                'national_service_code' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_national_service_code', 'national_service_code', '')),
                'nbs_code' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_nbs_code', 'nbs_code', '')),
                'iss_rate' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_iss_rate', 'iss_rate', '')),
                'municipality_code' => $municipalityCode,
                'complementary_info' => sanitize_textarea_field((string) $this->postValue('cloudxm_nfe_complementary_info', 'complementary_info', '')),
                'pis_cofins_cst' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_pis_cofins_cst', 'pis_cofins_cst', '')),
                'pis_cofins_retention_type' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_pis_cofins_retention_type', 'pis_cofins_retention_type', '')),
                'pis_cofins_vbc' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_pis_cofins_vbc', 'pis_cofins_vbc', '')),
                'pis_cofins_rate' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_pis_cofins_rate', 'pis_cofins_rate', '')),
                'pis_cofins_value' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_pis_cofins_value', 'pis_cofins_value', '')),
                'cofins_rate' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_cofins_rate', 'cofins_rate', '')),
                'cofins_value' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_cofins_value', 'cofins_value', '')),
                'social_security_retention' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_social_security_retention', 'social_security_retention', '')),
                'income_tax_retention' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_income_tax_retention', 'income_tax_retention', '')),
                'social_contribution_retention' => $this->sanitizeOptionalFloat((string) $this->postValue('cloudxm_nfe_social_contribution_retention', 'social_contribution_retention', '')),
                'debug_mode' => isset($_POST['cloudxm_nfe_debug_mode']) ? '1' : '0',
                'internal_contributor_code' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_internal_contributor_code', 'internal_contributor_code', '')),
                // Scheduling settings
                'schedule_timezone' => sanitize_text_field((string) $this->postValue('cloudxm_nfe_schedule_timezone', 'schedule_timezone', 'America/Sao_Paulo')),
                'webhook_secret' => $this->sanitizeWebhookSecret((string) $this->postValue('cloudxm_nfe_webhook_secret', 'webhook_secret', '')),
                'schedule_retry_on_failure' => isset($_POST['cloudxm_nfe_schedule_retry_on_failure']) ? '1' : '0',
                'schedule_max_retries' => $this->sanitizeScheduleMaxRetries((string) $this->postValue('cloudxm_nfe_schedule_max_retries', 'schedule_max_retries', '3')),
                'schedule_retry_interval_minutes' => $this->sanitizeScheduleRetryInterval((string) $this->postValue('cloudxm_nfe_schedule_retry_interval_minutes', 'schedule_retry_interval_minutes', '10')),
            ];

            $this->config->update($settings);
            delete_transient(self::TENANT_DEFAULTS_CACHE_KEY);
            delete_transient(self::COMPANIES_CACHE_KEY);

            // Clear company config cache for all companies
            global $wpdb;
            $wpdb->query(
                "DELETE FROM {$wpdb->options}
                WHERE option_name LIKE '_transient_" . self::COMPANY_CONFIG_CACHE_KEY . "%'"
            );
            $wpdb->query(
                "DELETE FROM {$wpdb->options}
                WHERE option_name LIKE '_transient_timeout_" . self::COMPANY_CONFIG_CACHE_KEY . "%'"
            );

            $this->tenantConfigCache->clear();

            $this->log()->info('nfe.settings.updated', [
                'environment' => $environment,
                'api_base_url' => $settings['api_base_url'],
            ]);

            wp_safe_redirect(admin_url('admin.php?page=cloudxm-nfe-settings&settings-updated=true'));
            exit;
        } catch (\Throwable $e) {
            $this->log()->error('nfe.settings.save_failed', [
                'error' => $e->getMessage(),
            ]);

            wp_safe_redirect(admin_url('admin.php?page=cloudxm-nfe-settings&settings-error=1'));
            exit;
        }
    }

    /**
     * Fetch tenant defaults from NFE server
     */
    private function fetchTenantDefaults(): void
    {
        $cached = get_transient(self::TENANT_DEFAULTS_CACHE_KEY);
        if (is_array($cached)) {
            $this->tenantDefaults = $cached;
            return;
        }

        if (!$this->apiClient->getApiToken()) {
            $this->tenantDefaults = null;
            return;
        }

        try {
            $defaults = $this->apiClient->withTimeout(5)->getTenantDefaults();
            $this->tenantDefaults = !empty($defaults) ? $defaults : null;

            if ($this->tenantDefaults !== null) {
                set_transient(self::TENANT_DEFAULTS_CACHE_KEY, $this->tenantDefaults, self::TENANT_DEFAULTS_CACHE_TTL);
            }
        } catch (\Throwable $e) {
            $this->log()->warning('nfe.tenant_defaults.fetch_failed', [
                'error' => $e->getMessage(),
            ]);
            $this->tenantDefaults = null;
        }
    }

    private function fetchCompanies(): void
    {
        $cached = get_transient(self::COMPANIES_CACHE_KEY);
        if (is_array($cached)) {
            $this->companies = array_values(array_filter($cached, fn($c) => is_array($c) && !empty($c['cnpj'])));
            return;
        }

        if (!$this->apiClient->getApiToken()) {
            $this->companies = [];
            return;
        }

        try {
            $companies = $this->apiClient->withTimeout(5)->getCompanies();
            $this->companies = is_array($companies) ? array_values(array_filter($companies, fn($c) => is_array($c) && !empty($c['cnpj']))) : [];

            if (!empty($this->companies)) {
                set_transient(self::COMPANIES_CACHE_KEY, $this->companies, self::COMPANIES_CACHE_TTL);
            }
        } catch (\Throwable $e) {
            $this->log()->warning('nfe.companies.fetch_failed', [
                'error' => $e->getMessage(),
            ]);
            $this->companies = [];
        }
    }

    private function fetchCompanyConfig(): void
    {
        $selectedCompanyCnpj = $this->config->get('selected_company_cnpj', '');

        // Find the company to use (selected, primary, or first available)
        $selectedCompany = null;

        if (empty($selectedCompanyCnpj)) {
            // No company selected - use primary company or first company as fallback
            foreach ($this->companies as $company) {
                if (!empty($company['is_primary'])) {
                    $selectedCompany = $company;
                    break;
                }
            }
            // If no primary company found, use the first company
            if (!$selectedCompany && !empty($this->companies)) {
                $selectedCompany = reset($this->companies);
            }
        } else {
            // Find the selected company by CNPJ
            foreach ($this->companies as $company) {
                if (($company['cnpj'] ?? '') === $selectedCompanyCnpj) {
                    $selectedCompany = $company;
                    break;
                }
            }
        }

        if (!$selectedCompany || !is_array($selectedCompany)) {
            if ($selectedCompany && !is_array($selectedCompany)) {
                $this->log()->warning('nfe.company_config.invalid_type', [
                    'type' => gettype($selectedCompany),
                ]);
            }
            $this->companyConfig = null;
            return;
        }

        // Check if federal taxes are already in the company list response
        if (isset($selectedCompany['federal_taxes'])) {
            $this->companyConfig = $selectedCompany;
            $this->log()->info('nfe.company_config.found_in_list', [
                'company_cnpj' => $selectedCompany['cnpj'] ?? 'unknown',
                'has_federal_taxes' => true,
            ]);
            return;
        }

        // Try to fetch detailed company config if ID is available
        if (empty($selectedCompany['id'] ?? '')) {
            $this->companyConfig = $selectedCompany;
            $this->log()->info('nfe.company_config.no_id', [
                'company_cnpj' => $selectedCompany['cnpj'] ?? 'unknown',
            ]);
            return;
        }

        $companyId = $selectedCompany['id'];
        $cacheKey = self::COMPANY_CONFIG_CACHE_KEY . $companyId;

        $cached = get_transient($cacheKey);
        if (is_array($cached)) {
            $this->companyConfig = $cached;
            return;
        }

        if (!$this->apiClient->getApiToken()) {
            $this->companyConfig = $selectedCompany;
            return;
        }

        try {
            $companyConfig = $this->apiClient->getCompanyConfig($companyId);
            // Merge with existing company data to preserve all fields
            $this->companyConfig = array_merge($selectedCompany, $companyConfig);

            $this->log()->info('nfe.company_config.fetched', [
                'company_id' => $companyId,
                'has_federal_taxes' => isset($companyConfig['federal_taxes']),
            ]);

            if (!empty($companyConfig)) {
                set_transient($cacheKey, $this->companyConfig, self::COMPANY_CONFIG_CACHE_TTL);
            }
        } catch (\Throwable $e) {
            $this->log()->warning('nfe.company_config.fetch_failed', [
                'company_id' => $companyId,
                'error' => $e->getMessage(),
            ]);
            // Use the company data from the list as fallback
            $this->companyConfig = $selectedCompany;
        }
    }

    private function getSettingsWithDefaults(): array
    {
        $settings = $this->config->getAll();
        $environment = $this->normalizeEnvironment((string) ($settings['environment'] ?? 'sandbox'));

        return array_merge(
            [
                'environment' => $environment,
                'api_base_url' => $settings['api_base_url'] ?? $this->getDefaultApiBaseUrl($environment),
                'token_sandbox' => $settings['token_sandbox'] ?? '',
                'token_production' => $settings['token_production'] ?? '',
                'token_staging' => $settings['token_staging'] ?? '',
                'token_custom' => $settings['token_custom'] ?? '',
                'selected_company_cnpj' => $settings['selected_company_cnpj'] ?? '',
                'cancel_days_limit' => (string) ($settings['cancel_days_limit'] ?? '5'),
                'auto_issue' => isset($settings['auto_issue']) ? (string) $settings['auto_issue'] : '1',
                'auto_issue_status' => (string) ($settings['auto_issue_status'] ?? 'manual'),
                'auto_cancel_status' => (string) ($settings['auto_cancel_status'] ?? 'disabled'),
                'enable_custom_description' => isset($settings['enable_custom_description']) ? (string) $settings['enable_custom_description'] : '1',
                'use_tenant_defaults' => isset($settings['use_tenant_defaults']) ? (string) $settings['use_tenant_defaults'] : '1',
                'municipal_service_code' => $settings['municipal_service_code'] ?? $settings['service_code'] ?? '',
                'national_service_code' => $settings['national_service_code'] ?? '',
                'nbs_code' => $settings['nbs_code'] ?? '',
                'iss_rate' => isset($settings['iss_rate']) ? (string) $settings['iss_rate'] : '',
                'municipality_code' => $settings['municipality_code'] ?? '',
                'complementary_info' => $settings['complementary_info'] ?? '',
                'pis_cofins_cst' => $settings['pis_cofins_cst'] ?? '',
                'pis_cofins_retention_type' => $settings['pis_cofins_retention_type'] ?? '',
                'pis_cofins_vbc' => isset($settings['pis_cofins_vbc']) ? (string) $settings['pis_cofins_vbc'] : '',
                'pis_cofins_rate' => isset($settings['pis_cofins_rate']) ? (string) $settings['pis_cofins_rate'] : '',
                'pis_cofins_value' => isset($settings['pis_cofins_value']) ? (string) $settings['pis_cofins_value'] : '',
                'cofins_rate' => isset($settings['cofins_rate']) ? (string) $settings['cofins_rate'] : '',
                'cofins_value' => isset($settings['cofins_value']) ? (string) $settings['cofins_value'] : '',
                'social_security_retention' => isset($settings['social_security_retention']) ? (string) $settings['social_security_retention'] : '',
                'income_tax_retention' => isset($settings['income_tax_retention']) ? (string) $settings['income_tax_retention'] : '',
                'social_contribution_retention' => isset($settings['social_contribution_retention']) ? (string) $settings['social_contribution_retention'] : '',
                'debug_mode' => isset($settings['debug_mode']) ? (string) $settings['debug_mode'] : '0',
                'internal_contributor_code' => $settings['internal_contributor_code'] ?? '',
                // Scheduling
                'schedule_timezone' => $settings['schedule_timezone'] ?? 'America/Sao_Paulo',
                'webhook_secret' => $settings['webhook_secret'] ?? '',
                'schedule_retry_on_failure' => isset($settings['schedule_retry_on_failure']) ? (string) $settings['schedule_retry_on_failure'] : '0',
                'schedule_max_retries' => isset($settings['schedule_max_retries']) ? (string) $settings['schedule_max_retries'] : '3',
                'schedule_retry_interval_minutes' => isset($settings['schedule_retry_interval_minutes']) ? (string) $settings['schedule_retry_interval_minutes'] : '10',
            ],
            $settings
        );
    }

    /**
     * Accept both legacy and current form key names.
     */
    private function postValue(string $legacyKey, string $newKey, mixed $default): mixed
    {
        if (isset($_POST[$legacyKey])) {
            return $_POST[$legacyKey];
        }
        if (isset($_POST[$newKey])) {
            return $_POST[$newKey];
        }
        return $default;
    }

    private function sanitizeOptionalFloat(string $value): string
    {
        $value = trim($value);
        if ($value === '') {
            return '';
        }

        return (string) floatval($value);
    }

    private function normalizeEnvironment(string $environment): string
    {
        $normalized = strtolower(trim($environment));
        // Normalize legacy values
        if ($normalized === 'homologation') {
            return 'sandbox';
        }
        if (!in_array($normalized, ['sandbox', 'production', 'staging', 'custom'], true)) {
            return 'sandbox';
        }
        return $normalized;
    }

    private function getDefaultApiBaseUrl(string $environment): string
    {
        if ($environment === 'production') {
            return 'https://nfe.cloudxm.com.br/api';
        }
        if ($environment === 'staging') {
            return 'https://stg-nfe.cloudxm.com.br/api';
        }
        if ($environment === 'custom') {
            return '';
        }
        return 'https://sandbox-nfe.cloudxm.com.br/api';
    }

    private function normalizeApiBaseUrl(string $value): string
    {
        $value = trim($value);
        if ($value === '') {
            return '';
        }

        // Accept local hosts/IPs without scheme (e.g., 192.168.0.74 or localhost:8080).
        if (!preg_match('#^https?://#i', $value)) {
            $value = 'http://' . ltrim($value, '/');
        }

        return rtrim(sanitize_text_field($value), '/');
    }

    private function sanitizeWebhookSecret(string $value): string
    {
        $value = trim($value);
        return $value !== '' ? sanitize_text_field($value) : '';
    }

    private function sanitizeScheduleMaxRetries(string $value): string
    {
        $int = (int) $value;
        if ($int < 1 || $int > 10) {
            throw new \InvalidArgumentException(__('Schedule max retries must be between 1 and 10', 'woocommerce-cloudxm-nfe'));
        }
        return (string) $int;
    }

    private function sanitizeScheduleRetryInterval(string $value): string
    {
        $int = (int) $value;
        if ($int < 1 || $int > 1440) {
            throw new \InvalidArgumentException(__('Schedule retry interval must be between 1 and 1440 minutes', 'woocommerce-cloudxm-nfe'));
        }
        return (string) $int;
    }
}
