<?php
/**
 * Extra Config Settings Registry
 * Singleton pattern for managing settings with caching
 *
 * @package AIAutoTool
 * @subpackage ExtraConfig
 * @since 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) exit; // Thoát nếu truy cập trực tiếp

/**
 * Settings Registry with Singleton pattern and caching
 */
class Aiautotool_Extra_Config_Settings_Registry {
    
    /**
     * Singleton instance
     *
     * @var Aiautotool_Extra_Config_Settings_Registry
     */
    private static $instance = null;
    
    /**
     * Settings cache
     *
     * @var array|null
     */
    private $settings = null;
    
    /**
     * Option name in database
     *
     * @var string
     */
    const OPTION_NAME = 'aiautotool_config_settings';
    
    /**
     * Cache group for object cache
     *
     * @var string
     */
    const CACHE_GROUP = 'aiautotool_extra_config';
    
    /**
     * Cache key
     *
     * @var string
     */
    const CACHE_KEY = 'settings';
    
    /**
     * Default settings
     *
     * @var array
     */
    private $defaults = array(
        // Editor
        'tool-blockcomment'  => 1,
        'tool-edit1'         => 1,
        'tool-edit11'        => 1,
        'tool-widget1'       => 1,
        
        // Management
        'tool-mana1'         => 0,
        'tool-mana2'         => 0,
        'tool-mana3'         => 0,
        
        // Speed optimization
        'speed-off1'         => 1,
        'speed-off2'         => 1,
        'speed-off3'         => 1,
        'speed-off4'         => 1,
        'speed-link1'        => 1,
        'speed-link2'        => 1,
        'speed-zip1'         => 0,
        'speed-data1'        => 0,
        'speed-data11'       => 3,
        'speed-data2'        => 0,
        'speed-data21'       => 1,
        
        // Security
        'scuri-off1'         => 0,
        'scuri-off2'         => 0,
        'scuri-off3'         => 0,
        'scuri-off4'         => 0,
        'scuri-off5'         => 0,
        'scuri-off6'         => 0,
        'scuri-verof1'       => 0,
        'scuri-verof2'       => 0,
        'scuri-sql1'         => 0,
    );
    
    /**
     * Private constructor to enforce singleton
     */
    private function __construct() {
        // Private constructor
    }
    
    /**
     * Get singleton instance
     *
     * @return Aiautotool_Extra_Config_Settings_Registry
     */
    public static function instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        
        return self::$instance;
    }
    
    /**
     * Prevent cloning
     */
    private function __clone() {
        // Prevent cloning
    }
    
    /**
     * Prevent unserialization
     */
    public function __wakeup() {
        // Prevent unserialization
    }
    
    /**
     * Load settings from database
     *
     * @param bool $force Force reload from database
     * @return array Settings array
     */
    private function load_settings($force = false) {
        // Return cached if available and not forcing reload
        if (null !== $this->settings && !$force) {
            return $this->settings;
        }
        
        // Try to get from WordPress object cache
        $cached = wp_cache_get(self::CACHE_KEY, self::CACHE_GROUP);
        if (false !== $cached && !$force) {
            $this->settings = $cached;
            return $this->settings;
        }
        
        // Load from database
        $settings = get_option(self::OPTION_NAME, array());
        
        // Merge with defaults
        $this->settings = wp_parse_args($settings, $this->defaults);
        
        // Cache in WordPress object cache
        wp_cache_set(self::CACHE_KEY, $this->settings, self::CACHE_GROUP, HOUR_IN_SECONDS);
        
        return $this->settings;
    }
    
    /**
     * Get a setting value
     *
     * @param string $key     Setting key
     * @param mixed  $default Default value if not found
     * @return mixed Setting value
     */
    public function get($key, $default = null) {
        $settings = $this->load_settings();
        
        if (!isset($settings[$key])) {
            // Return provided default or from defaults array
            return null !== $default ? $default : $this->get_default($key);
        }
        
        return $settings[$key];
    }
    
    /**
     * Get multiple settings
     *
     * @param array $keys Array of setting keys
     * @return array Associative array of settings
     */
    public function get_multiple($keys) {
        $settings = $this->load_settings();
        $result = array();
        
        foreach ($keys as $key) {
            $result[$key] = isset($settings[$key]) ? $settings[$key] : $this->get_default($key);
        }
        
        return $result;
    }
    
    /**
     * Get all settings
     *
     * @return array All settings
     */
    public function get_all() {
        return $this->load_settings();
    }
    
    /**
     * Check if a setting exists
     *
     * @param string $key Setting key
     * @return bool True if exists
     */
    public function has($key) {
        $settings = $this->load_settings();
        return isset($settings[$key]);
    }
    
    /**
     * Check if a setting is enabled (for boolean settings)
     *
     * @param string $key Setting key
     * @return bool True if enabled
     */
    public function is_enabled($key) {
        $value = $this->get($key, 0);
        return (int) $value === 1;
    }
    
    /**
     * Update a single setting
     *
     * @param string $key   Setting key
     * @param mixed  $value Setting value
     * @return bool True on success
     */
    public function set($key, $value) {
        $settings = $this->load_settings();
        $settings[$key] = $value;
        
        return $this->save($settings);
    }
    
    /**
     * Update multiple settings
     *
     * @param array $settings Associative array of settings
     * @param bool  $merge    Whether to merge with existing settings
     * @return bool True on success
     */
    public function update($settings, $merge = true) {
        if (!is_array($settings)) {
            return false;
        }
        
        if ($merge) {
            $current = $this->load_settings();
            $settings = array_merge($current, $settings);
        }
        
        return $this->save($settings);
    }
    
    /**
     * Save settings to database
     *
     * @param array $settings Settings to save
     * @return bool True on success
     */
    private function save($settings) {
        // Update in database
        $updated = update_option(self::OPTION_NAME, $settings, false);
        
        if ($updated) {
            // Update local cache
            $this->settings = $settings;
            
            // Update WordPress object cache
            wp_cache_set(self::CACHE_KEY, $settings, self::CACHE_GROUP, HOUR_IN_SECONDS);
            
            // Fire action hook
            do_action('aiautotool_extra_config_settings_updated', $settings);
        }
        
        return $updated;
    }
    
    /**
     * Delete a setting
     *
     * @param string $key Setting key
     * @return bool True on success
     */
    public function delete($key) {
        $settings = $this->load_settings();
        
        if (!isset($settings[$key])) {
            return false;
        }
        
        unset($settings[$key]);
        return $this->save($settings);
    }
    
    /**
     * Reset all settings to defaults
     *
     * @return bool True on success
     */
    public function reset() {
        return $this->save($this->defaults);
    }
    
    /**
     * Reset a specific setting to default
     *
     * @param string $key Setting key
     * @return bool True on success
     */
    public function reset_setting($key) {
        if (!isset($this->defaults[$key])) {
            return false;
        }
        
        return $this->set($key, $this->defaults[$key]);
    }
    
    /**
     * Get default value for a setting
     *
     * @param string $key Setting key
     * @return mixed Default value or null
     */
    public function get_default($key) {
        return isset($this->defaults[$key]) ? $this->defaults[$key] : null;
    }
    
    /**
     * Get all default settings
     *
     * @return array Default settings
     */
    public function get_defaults() {
        return $this->defaults;
    }
    
    /**
     * Clear all caches
     *
     * @return void
     */
    public function clear_cache() {
        $this->settings = null;
        wp_cache_delete(self::CACHE_KEY, self::CACHE_GROUP);
        
        // Force reload on next access
        $this->load_settings(true);
    }
    
    /**
     * Export settings
     *
     * @return string JSON encoded settings
     */
    public function export() {
        $settings = $this->load_settings();
        
        $export_data = array(
            'version'   => AIAUTOTOOL_VS,
            'timestamp' => current_time('timestamp'),
            'settings'  => $settings,
        );
        
        return wp_json_encode($export_data, JSON_PRETTY_PRINT);
    }
    
    /**
     * Import settings
     *
     * @param string $json JSON encoded settings
     * @return bool|WP_Error True on success or WP_Error on failure
     */
    public function import($json) {
        $data = json_decode($json, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            return new WP_Error(
                'invalid_json',
                __('Invalid JSON format', 'ai-auto-tool')
            );
        }
        
        if (!isset($data['settings']) || !is_array($data['settings'])) {
            return new WP_Error(
                'invalid_format',
                __('Invalid settings format', 'ai-auto-tool')
            );
        }
        
        // Validate settings using security class
        require_once plugin_dir_path(__FILE__) . 'class-security.php';
        $security = new Aiautotool_Extra_Config_Security();
        $validated = $security->sanitize_settings($data['settings']);
        
        // Save validated settings
        return $this->save($validated);
    }
    
    /**
     * Get settings by category
     *
     * @param string $category Category prefix (e.g., 'speed', 'scuri', 'tool')
     * @return array Settings in category
     */
    public function get_by_category($category) {
        $settings = $this->load_settings();
        $result = array();
        
        foreach ($settings as $key => $value) {
            if (strpos($key, $category . '-') === 0) {
                $result[$key] = $value;
            }
        }
        
        return $result;
    }
    
    /**
     * Get enabled features
     *
     * @return array Array of enabled feature keys
     */
    public function get_enabled_features() {
        $settings = $this->load_settings();
        $enabled = array();
        
        foreach ($settings as $key => $value) {
            if ((int) $value === 1) {
                $enabled[] = $key;
            }
        }
        
        return $enabled;
    }
    
    /**
     * Get statistics about settings
     *
     * @return array Statistics
     */
    public function get_stats() {
        $settings = $this->load_settings();
        $enabled_count = 0;
        $categories = array();
        
        foreach ($settings as $key => $value) {
            if ((int) $value === 1) {
                $enabled_count++;
            }
            
            // Extract category
            $parts = explode('-', $key);
            if (isset($parts[0])) {
                $category = $parts[0];
                if (!isset($categories[$category])) {
                    $categories[$category] = 0;
                }
                if ((int) $value === 1) {
                    $categories[$category]++;
                }
            }
        }
        
        return array(
            'total_settings'    => count($settings),
            'enabled_settings'  => $enabled_count,
            'disabled_settings' => count($settings) - $enabled_count,
            'categories'        => $categories,
            'last_modified'     => get_option(self::OPTION_NAME . '_modified', ''),
        );
    }
}


