<?php
namespace Blazemedia\Affiliation\AdminUserInterface\Settings;

use Blazemedia\Affiliation\AdminUserInterface\Settings\Capability;
use Blazemedia\Affiliation\AdminUserInterface\Settings\Components\FieldRenderer;
use Blazemedia\Affiliation\AdminUserInterface\Settings\Components\ActionButtons;
use Blazemedia\Affiliation\AdminUserInterface\Settings\Components\StyleManager;

/**
 * WordPress Settings Page for Affiliation Plugin
 */
class SettingPage {

    private const OPTION_NAME = 'affiliation_settings_option_name';
    private const OPTION_GROUP = 'affiliation_settings_option_group';
    private const PAGE_SLUG = 'affiliation-settings';
    private const SECTION_ID = 'affiliation_settings_setting_section';
    
    private $options;
    private FieldRenderer $fieldRenderer;
    private ActionButtons $actionButtons;
    private StyleManager $styleManager;

    public function __construct() {
        $this->fieldRenderer = new FieldRenderer(self::OPTION_NAME);
        $this->actionButtons = new ActionButtons(self::PAGE_SLUG);
        $this->styleManager = new StyleManager();
        
        // Esegui migrazione se necessario
        $this->migrateEnvironmentSettings();
        
        add_action('admin_menu', [$this, 'addMenuPages']);
        add_action('admin_init', [$this, 'initSettingsPage']);
        add_action('admin_init', [$this, 'handleFormActions']);
        add_action('admin_enqueue_scripts', [$this, 'enqueueStyles']);
    }

    /**
     * Enqueue admin styles
     */
    public function enqueueStyles($hook): void {
        if (strpos($hook, self::PAGE_SLUG) === false) return;
        
        wp_enqueue_style(
            'affiliation-admin-settings',
            plugin_dir_url(__FILE__) . 'assets/admin-settings.css',
            [],
            '1.0.0'
        );
    }

    /**
     * Add menu pages to WordPress admin
     */
    public function addMenuPages(): void {
        add_menu_page(
            'Affiliation Management',
            'Affiliation Management',
            'manage_options',
            'affiliation-management',
            '',
            'dashicons-chart-area',
            65
        );

        add_submenu_page(
            'affiliation-management',
            'Affiliation Settings',
            'Settings',
            'manage_options',
            self::PAGE_SLUG,
            [$this, 'renderAdminPage']
        );
    }

    /**
     * Render the main admin page
     */
    public function renderAdminPage(): void {
        if (!current_user_can(Capability::AFFILIATION_CAP)) {
            wp_die('Non hai i permessi per visualizzare questa pagina');
        }

        // Ensure defaults on first install
        $this->ensureDefaultOptions();

        $this->options = get_option(self::OPTION_NAME);
        
        // Show error if API Secret is missing
        if (!isset($this->options['api_secret']) || trim((string)$this->options['api_secret']) === '') {
            add_settings_error(
                self::OPTION_NAME,
                'api_secret_missing',
                'API Secret mancante. Inserisci il valore per poter utilizzare il plugin.',
                'error'
            );
        }
        ?>
        <div class="wrap affiliation-settings-wrap">
            <div class="affiliation-header">
                <h1><i class="dashicons dashicons-chart-area"></i> Affiliation Settings</h1>
                <p class="description">Configura le impostazioni del plugin di affiliazione</p>
            </div>
            
            <?php $this->actionButtons->renderMessages(); ?>
            <?php settings_errors(); ?>
            
            <div class="affiliation-content">
                <div class="settings-form-container">
                    <form method="post" action="options.php" class="affiliation-form">
                        <?php
                        settings_fields(self::OPTION_GROUP);
                        do_settings_sections(self::PAGE_SLUG . '-admin');
                        ?>
                        <div class="submit-container">
                            <?php submit_button('Salva Impostazioni', 'primary', 'submit', false, ['class' => 'button-hero']); ?>
                        </div>
                    </form>
                </div>
                
                <div class="actions-container">
                    <?php $this->actionButtons->render(); ?>
                </div>
            </div>
        </div>
        <?php
    }

    /**
     * Ensure default options exist on first installation.
     */
    private function ensureDefaultOptions(): void {
        $current = get_option(self::OPTION_NAME);
        if ($current === false || !is_array($current)) {
            $current = [];
        }

        // Set default domain if missing/empty
        if (!isset($current['domain_2']) || trim((string) $current['domain_2']) === '') {
            $current['domain_2'] = $this->getDefaultDomain();
        }

        // Set default disclaimer if missing/empty
        if (!isset($current['disclaimer']) || trim(wp_strip_all_tags((string) $current['disclaimer'])) === '') {
            $current['disclaimer'] = $this->getDefaultDisclaimer();
        }

        // Ensure key exists for api_secret without setting a default
        if (!array_key_exists('api_secret', $current)) {
            $current['api_secret'] = '';
        }

        update_option(self::OPTION_NAME, $current);
    }

    /**
     * Compute a sensible default domain from the site URL, removing subdomains,
     * paths and queries, and keeping only the registrable domain.
     */
    private function getDefaultDomain(): string {
        $host = wp_parse_url(home_url(), PHP_URL_HOST);
        if (!is_string($host) || $host === '') return '';

        $host = strtolower(trim($host, "."));

        // If host is an IP address, return as is
        if (filter_var($host, FILTER_VALIDATE_IP)) {
            return $host;
        }

        // Split labels and remove common leading subdomain(s)
        $labels = array_values(array_filter(explode('.', $host), fn($l) => $l !== ''));
        while (count($labels) > 0 && in_array($labels[0], ['www', 'm'], true)) {
            array_shift($labels);
        }

        $num = count($labels);
        if ($num === 0) return '';
        if ($num === 1) return $labels[0];

        $tld = $labels[$num - 1];

        // Generic rule without static arrays:
        // - For ccTLDs (2-letter TLDs), keep last 3 labels if available (example.co.uk)
        // - Otherwise keep last 2 labels (example.com)
        if (strlen($tld) === 2 && $num >= 3) {
            return $labels[$num - 3] . '.' . $labels[$num - 2] . '.' . $labels[$num - 1];
        }

        return $labels[$num - 2] . '.' . $labels[$num - 1];
    }

    /**
     * Default disclaimer text used on first install or when empty
     */
    private function getDefaultDisclaimer(): string {
        return 'Questo articolo contiene link di affiliazione: acquisti o ordini effettuati tramite tali link permetteranno al nostro sito di ricevere una commissione nel rispetto del <a href="https://www.blazemedia.it/codice-etico/" target="_blank" rel="nofollow">codice etico</a>. Le offerte potrebbero subire variazioni di prezzo dopo la pubblicazione.';
    }

    /**
     * Initialize settings page
     */
    public function initSettingsPage(): void {
        register_setting(
            self::OPTION_GROUP,
            self::OPTION_NAME,
            [$this, 'sanitizeOptions']
        );

        add_settings_section(
            self::SECTION_ID,
            '',
            [$this, 'renderSectionInfo'],
            self::PAGE_SLUG . '-admin'
        );

        $this->addSettingsFields();
    }

    /**
     * Add all settings fields
     */
    private function addSettingsFields(): void {
        // Ottieni tutti i post types pubblici
        $postTypes = get_post_types(['public' => true], 'objects');
        $postTypeOptions = [];
        
        foreach ($postTypes as $postType) {
            $postTypeOptions[$postType->name] = $postType->labels->name;
        }
        
        $fields = [
            'post_types_0' => [
                'title' => 'Post Types', 
                'type' => 'multiselect', 
                'options' => $postTypeOptions,
                'description' => 'Seleziona i tipi di post supportati dal plugin'
            ],
            'restrizioni_1' => ['title' => 'Restrizioni', 'type' => 'text', 'description' => 'Livello di restrizioni'],
            'domain_2' => ['title' => 'Dominio', 'type' => 'text', 'description' => 'Dominio del servizio di affiliazione'],
            'api_secret' => ['title' => 'API Secret', 'type' => 'password', 'description' => 'Chiave segreta per autenticare le chiamate al Rendering Manager', 'required' => true],
            'disclaimer' => ['title' => 'Disclaimer', 'type' => 'textarea', 'description' => 'Testo del disclaimer di default']
        ];

        foreach ($fields as $id => $config) {
            add_settings_field(
                $id,
                $config['title'],
                [$this, 'renderField'],
                self::PAGE_SLUG . '-admin',
                self::SECTION_ID,
                ['field_id' => $id, 'config' => $config]
            );
        }
    }

    /**
     * Render individual field
     */
    public function renderField($args): void {
        $field_id = $args['field_id'];
        $config = $args['config'];
        $value = $this->options[$field_id] ?? '';
        
        $this->fieldRenderer->render($field_id, $config, $value);
    }

    /**
     * Sanitize options
     */
    public function sanitizeOptions($input): array {
        // Merge with existing options to avoid dropping keys like 'ambiente' and 'cache'
        $existing = get_option(self::OPTION_NAME);
        $sanitized = is_array($existing) ? $existing : [];

        $text_fields = ['post_types_0', 'restrizioni_1', 'domain_2'];
        foreach ($text_fields as $field) {
            if (isset($input[$field])) {
                $sanitized[$field] = sanitize_text_field($input[$field]);
            }
        }

        // Handle API Secret (do not overwrite with empty; trim spaces)
        if (array_key_exists('api_secret', $input)) {
            $newSecret = trim((string)$input['api_secret']);
            if ($newSecret !== '') {
                $sanitized['api_secret'] = $newSecret;
            }
        }

        if (isset($input['disclaimer'])) {
            $sanitized['disclaimer'] = wp_kses_post($input['disclaimer']);
        }

        $select_fields = ['ambiente', 'cache'];
        foreach ($select_fields as $field) {
            if (isset($input[$field])) {
                $sanitized[$field] = sanitize_text_field($input[$field]);
            }
        }

        return $sanitized;
    }

    /**
     * Section info callback
     */
    public function renderSectionInfo(): void {
        // echo '<div class="settings-section-description">Configura i parametri principali del plugin di affiliazione.</div>';
        echo "";
    }

    /**
     * Handle form actions
     */
    public function handleFormActions(): void {
        $this->actionButtons->handleActions();
    }

    /**
     * Migra automaticamente i valori di ambiente obsoleti
     */
    private function migrateEnvironmentSettings(): void {
        $options = get_option(self::OPTION_NAME);
        
        if (isset($options['ambiente']) && $options['ambiente'] === 'newlp') {
            $options['ambiente'] = 'prod';
            update_option(self::OPTION_NAME, $options);
        }
    }
}