<?php

declare(strict_types=1);
if (!defined('WPINC')) {
    die();
}
/**
 * Class CPEPAI_Options_Service
 * Handles the registration and management of plugin options.
 */
class CPEPAI_Options_Service
{
    /**
     * The option group name.
     *
     * @var string
     */
    private string $option_group = 'cpepai_options';

    /**
     * The option name.
     *
     * @var string
     */
    private string $option_name = 'cpepai_settings';

    /**
     * Register the service.
     *
     * @return void
     */
    public function register(): void
    {
        add_action('admin_init', [$this, 'register_settings']);
    }

    /**
     * Register plugin settings and options.
     *
     * @return void
     */
    public function register_settings(): void
    {
        // Register the settings group
        register_setting($this->option_group, $this->option_name, [
            'type' => 'array',
            'sanitize_callback' => [$this, 'sanitize_settings'],
            'default' => $this->get_default_settings()
        ]);
    }

    /**
     * Sanitize settings data.
     *
     * @param array $input Raw input data.
     * @return array Sanitized data.
     */
    public function sanitize_settings(array $input): array
    {
        $sanitized = [];
        // Use get_field_definitions() instead of get_field_configurations() to include non-visible fields
        $field_definitions = $this->get_field_definitions();

        foreach ($field_definitions as $key => $config) {
            // For checkboxes, if not present in input, set to false
            if ($config['type'] === 'checkbox') {
                $sanitized[$key] = isset($input[$key]) ? (bool) $input[$key] : false;
            } elseif (isset($input[$key])) {
                switch ($config['type']) {
                    case 'text':
                    case 'password':
                    case 'email':
                    case 'url':
                        $sanitized[$key] = sanitize_text_field($input[$key]);
                        break;
                    case 'textarea':
                        $sanitized[$key] = sanitize_textarea_field($input[$key]);
                        break;
                    case 'number':
                        $sanitized[$key] = intval($input[$key]);
                        break;
                    case 'select':
                    case 'radio':
                        // Validate against allowed options
                        if (in_array($input[$key], array_keys($config['options'] ?? []))) {
                            $sanitized[$key] = sanitize_text_field($input[$key]);
                        }
                        break;
                    default:
                        $sanitized[$key] = sanitize_text_field($input[$key]);
                }
            }
        }

        // Also handle any additional fields that might not be in field definitions
        // (e.g., goals, language from onboarding)
        foreach ($input as $key => $value) {
            if (!isset($sanitized[$key])) {
                // Sanitize unknown fields as text or preserve arrays
                if (is_array($value)) {
                    $sanitized[$key] = array_map('sanitize_text_field', $value);
                } else {
                    $sanitized[$key] = sanitize_text_field($value);
                }
            }
        }

        return $sanitized;
    }

    /**
     * Get field configurations with default values - single source of truth.
     *
     * @return array Field configurations with default values.
     */
    private function get_field_definitions(): array
    {
        return [
            'publish_interval_days' => [
                'type' => 'number',
                'label' => __('Publish Interval (Days)', 'cplanteam-ai-content-planner'),
                'description' => __('How often posts should be published (in days).', 'cplanteam-ai-content-planner'),
                'required' => false,
                'placeholder' => __('Enter number of days', 'cplanteam-ai-content-planner'),
                'default' => 7,
                'min' => 1,
                'max' => 365
            ],
            'onboarding_completed' => [
                'type' => 'checkbox',
                'label' => __('Onboarding Completed', 'cplanteam-ai-content-planner'),
                'description' => __(
                    'Indicates if the user has completed the onboarding process.',
                    'cplanteam-ai-content-planner'
                ),
                'required' => false,
                'default' => false,
                'visible' => false
            ],
            'tutorial_watched' => [
                'type' => 'checkbox',
                'label' => __('Tutorial Watched', 'cplanteam-ai-content-planner'),
                'description' => __('Indicates if the user has watched the tutorial.', 'cplanteam-ai-content-planner'),
                'required' => false,
                'default' => false,
                'visible' => false
            ],
            'post_editor_format' => [
                'type' => 'select',
                'label' => __('Post Editor', 'cplanteam-ai-content-planner'),
                'description' => __(
                    'Choose how the post should be saved. Auto detects the editor used on your site.',
                    'cplanteam-ai-content-planner'
                ),
                'required' => false,
                'default' => 'auto',
                'options' => [
                    'auto' => __('Auto', 'cplanteam-ai-content-planner'),
                    'gutenberg' => __('Gutenberg', 'cplanteam-ai-content-planner'),
                    'elementor' => __('Elementor', 'cplanteam-ai-content-planner'),
                    'classic' => __('Classic', 'cplanteam-ai-content-planner')
                ]
            ]
        ];
    }

    /**
     * Get default settings.
     *
     * @return array Default settings array.
     */
    public function get_default_settings(): array
    {
        $defaults = [];
        $field_definitions = $this->get_field_definitions();

        foreach ($field_definitions as $key => $config) {
            $defaults[$key] = $config['default'];
        }

        return $defaults;
    }

    /**
     * Get field configurations for dynamic rendering.
     *
     * @return array Field configurations.
     */
    public function get_field_configurations(): array
    {
        $configurations = [];
        $field_definitions = $this->get_field_definitions();

        foreach ($field_definitions as $key => $config) {
            // Skip non-visible fields
            if (isset($config['visible']) && $config['visible'] === false) {
                continue;
            }

            // Remove the default value from the configuration array
            $configurations[$key] = $config;
            unset($configurations[$key]['default']);
        }

        return $configurations;
    }

    /**
     * Get all available settings with their values.
     *
     * @return array All settings in key-value format.
     */
    public function get_settings(): array
    {
        $defaults = $this->get_default_settings();
        $settings = [];

        foreach ($defaults as $key => $default_value) {
            $settings[$key] = $this->get_setting($key, $default_value);
        }

        return $settings;
    }

    /**
     * Get a specific setting value.
     *
     * @param string $key Setting key.
     * @param mixed $default Default value if setting doesn't exist.
     * @return mixed Setting value or default.
     */
    public function get_setting(string $key, $default = null)
    {
        $settings = get_option($this->option_name, $this->get_default_settings());
        return $settings[$key] ?? $default;
    }

    /**
     * Update a specific setting value.
     *
     * @param string $key Setting key.
     * @param mixed $value Setting value.
     * @return bool True if option value has changed, false if not or if update failed.
     */
    public function update_setting(string $key, $value): bool
    {
        $settings = get_option($this->option_name, $this->get_default_settings());
        $settings[$key] = $value;
        return update_option($this->option_name, $settings);
    }

    /**
     * Update multiple settings at once.
     *
     * @param array $settings_array Array of settings to update.
     * @return bool True if option value has changed, false if not or if update failed.
     */
    public function update_settings(array $settings_array): bool
    {
        $current_settings = get_option($this->option_name, $this->get_default_settings());
        $updated_settings = array_merge($current_settings, $settings_array);

        // Check if settings have actually changed
        if ($current_settings === $updated_settings) {
            return true; // Consider this a success since the desired state is achieved
        }

        $result = update_option($this->option_name, $updated_settings);
        return $result;
    }

    /**
     * Delete all plugin options.
     *
     * @return void
     */
    public function delete_all_options(): void
    {
        delete_option($this->option_name);
    }
}
