<?php
/**
 * Settings Schema Validation System
 *
 * @package HvnlyNab\Api\Type\Settings
 * @since 2.0.3
 */

namespace HvnlyNab\Api\Type\Settings;

// Exit if accessed directly.
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Settings Schema Definition and Validation Class
 * 
 * @since 2.0.3
 */
class SettingsSchema
{
    /**
     * Schema cache
     *
     * @var array|null
     */
    private static $schema = null;
    
    /**
     * Valid groups list
     *
     * @var array
     */
    private static $valid_groups = ['general', 'design', 'search', 'properties', 'shortcodes', 'property-details', 'preloader', 'map'];

    /**
     * Map provider options
     *
     * @var array
     */
    private static $map_providers = ['leaflet', 'openstreetmap', 'google'];

    /**
     * Map style options
     *
     * @var array
     */
    private static $map_styles = ['standard', 'satellite', 'hybrid', 'terrain'];

    /**
     * Google map type options
     *
     * @var array
     */
    private static $google_map_types = ['roadmap', 'satellite', 'hybrid', 'terrain'];

    /**
     * Zoom level options (min, max)
     *
     * @var array
     */
    private static $zoom_range = ['min' => 1, 'max' => 20];
    
    /**
     * Initialize and return the full schema
     *
     * @return array
     */
    private static function init_schema()
    {
        if (null !== self::$schema) {
            return self::$schema;
        }
        
        self::$schema = [

            // ==============================================
            // PRELOADER GROUP
            // ==============================================
            'preloader' => [
                // Global settings
                'hvnly_enable_preloader' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_preloader_animation' => [
                    'type' => 'string',
                    'default' => 'shimmer',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_preloader_min_display' => [
                    'type' => 'integer',
                    'default' => 300,
                    'sanitize' => 'absint',
                ],
                
                // Component specific settings
                'hvnly_preloader_top_search' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_preloader_filter_sidebar' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_preloader_property_grid' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_preloader_property_list' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_preloader_view_controls' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_preloader_load_more' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_preloader_pagination' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
            ],

            // ==============================================
            // MAP GROUP - NEW
            // ==============================================
            'map' => [
                // Map Provider Configuration
                'hvnly_map_provider' => [
                    'type' => 'string',
                    'default' => 'leaflet',
                    'sanitize' => 'sanitize_text_field',
                    'validate_callback' => 'validate_map_provider',
                ],
                'hvnly_map_api_key' => [
                    'type' => 'string',
                    'default' => '',
                    'sanitize' => 'sanitize_text_field',
                ],
                
                // Map Display Settings
                'hvnly_default_lat' => [
                    'type' => 'string',
                    'default' => '51.514939',
                    'sanitize' => 'sanitize_text_field',
                    'validate_callback' => 'validate_coordinate',
                ],
                'hvnly_default_lng' => [
                    'type' => 'string',
                    'default' => '-0.091839',
                    'sanitize' => 'sanitize_text_field',
                    'validate_callback' => 'validate_coordinate',
                ],
                'hvnly_map_zoom' => [
                    'type' => 'integer',
                    'default' => 12,
                    'sanitize' => 'absint',
                    'validate_callback' => 'validate_zoom_level',
                ],
                'hvnly_map_style' => [
                    'type' => 'string',
                    'default' => 'standard',
                    'sanitize' => 'sanitize_text_field',
                    'validate_callback' => 'validate_map_style',
                ],
                
                // Marker Settings
                'hvnly_cluster_markers' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_custom_marker' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_marker_color' => [
                    'type' => 'string',
                    'default' => '#6C60FE',
                    'sanitize' => 'sanitize_hex_color',
                ],
                
                // Map UI Settings
                'hvnly_show_fullscreen' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_show_zoom_control' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_show_scroll_wheel' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                
                // Google Maps Specific
                'hvnly_google_map_type' => [
                    'type' => 'string',
                    'default' => 'roadmap',
                    'sanitize' => 'sanitize_text_field',
                    'validate_callback' => 'validate_google_map_type',
                ],
                // Google Maps Specific
                'hvnly_google_map_type' => [
                    'type' => 'string',
                    'default' => 'roadmap',
                    'sanitize' => 'sanitize_text_field',
                    'validate_callback' => 'validate_google_map_type',
                ],
                
                // OpenStreetMap Specific
                'hvnly_osm_tile_url' => [
                    'type' => 'string',
                    'default' => 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_osm_attribution' => [
                    'type' => 'string',
                    'default' => '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
                    'sanitize' => 'wp_kses_post',
                ],


                
            ],

            // ==============================================
            // GENERAL GROUP - Currency, Misc
            // ==============================================
            'general' => [
                // Currency Settings
                'hvnly_EnabledCurrencyFormat' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_thousandSeparator' => [
                    'type' => 'string',
                    'default' => ',',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_decimalSeparator' => [
                    'type' => 'string',
                    'default' => '.',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_numberOfDecimals' => [
                    'type' => 'string',
                    'default' => '0',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_thousandText' => [
                    'type' => 'string',
                    'default' => 'K',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_millionText' => [
                    'type' => 'string',
                    'default' => 'M',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_billionText' => [
                    'type' => 'string',
                    'default' => 'B',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_currencyType' => [
                    'type' => 'string',
                    'default' => 'USD',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_currencyPositionType' => [
                    'type' => 'string',
                    'default' => 'LEFT',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_priceOnCallText' => [
                    'type' => 'string',
                    'default' => 'priceOnCallNone',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_priceFormat' => [
                    'type' => 'string',
                    'default' => 'comma',
                    'sanitize' => 'sanitize_text_field',
                ],
                
                // Misc Settings
                'hvnly_EnabledGutenbergEditor' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_EnabledSocialShare' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_defaultCity' => [
                    'type' => 'string',
                    'default' => 'Birmingham',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_defaultState' => [
                    'type' => 'string',
                    'default' => 'Scotland',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_countryType' => [
                    'type' => 'string',
                    'default' => 'GB',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_enableSocialShare' => [
                    'type' => 'array',
                    'default' => ['facebook', 'twitter'],
                    'sanitize' => null,
                ],
            ],
            
            // ==============================================
            // DESIGN GROUP - Colors
            // ==============================================
            'design' => [
                'hvnly_brandColor' => [
                    'type' => 'string',
                    'default' => '#6C60FE',
                    'sanitize' => 'sanitize_hex_color',
                ],
                'hvnly_secondaryColor' => [
                    'type' => 'string',
                    'default' => '#764ba2',
                    'sanitize' => 'sanitize_hex_color',
                ],
                'hvnly_linkColor' => [
                    'type' => 'string',
                    'default' => '#1E1E2F',
                    'sanitize' => 'sanitize_hex_color',
                ],
                'hvnly_linkHoverColor' => [
                    'type' => 'string',
                    'default' => '#764ba2',
                    'sanitize' => 'sanitize_hex_color',
                ],
                'hvnly_titleColor' => [
                    'type' => 'string',
                    'default' => '#1E1E2F',
                    'sanitize' => 'sanitize_hex_color',
                ],
                'hvnly_primaryTextColor' => [
                    'type' => 'string',
                    'default' => '#1E1E2F',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_secondaryTextColor' => [
                    'type' => 'string',
                    'default' => '#555555',
                    'sanitize' => 'sanitize_text_field',
                ],
            ],
            
            // ==============================================
            // SEARCH GROUP - Search Settings
            // ==============================================
            'search' => [
                // Search Bar Settings
                'hvnly_searchBarTitle' => [
                    'type' => 'string',
                    'default' => 'Search Properties',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_searchButtonText' => [
                    'type' => 'string',
                    'default' => 'Search',
                    'sanitize' => 'sanitize_text_field',
                ],
                
                'hvnly_enableAjaxLoadMore' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_AjaxLoadMoreButtonText' => [
                    'type' => 'string',
                    'default' => 'Load More',
                    'sanitize' => 'sanitize_text_field',
                ],
                // Hide Options
                'hvnly_hideTopSearchTitle' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_hideTopSearchBar' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_hideLeftSearchBar' => [
                    'type' => 'boolean',
                    'default' => false,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                
                // Layout Settings
                'hvnly_numberOfColumns' => [
                    'type' => 'string',
                    'default' => '3',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_searchResultPerpage' => [
                    'type' => 'string',
                    'default' => '6',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_sidebarLayoutType' => [
                    'type' => 'string',
                    'default' => 'LEFT',
                    'sanitize' => 'sanitize_text_field',
                ],
                
                // Property View Settings
                'hvnly_propertyViewType' => [
                    'type' => 'string',
                    'default' => 'GRID',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertyOrderByType' => [
                    'type' => 'string',
                    'default' => 'TITLE',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertySortByType' => [
                    'type' => 'string',
                    'default' => 'date',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertyDepartmentOrderByType' => [
                    'type' => 'string',
                    'default' => 'RENT',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertyThumbnailSize' => [
                    'type' => 'string',
                    'default' => 'thumbnail',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertiesPerPage' => [
                    'type' => 'integer',
                    'default' => 6,
                    'sanitize' => 'absint',
                ],
                // Search Fields Configuration
                'hvnly_search_fields' => [
                    'type' => 'array',
                    'default' => [],
                    'sanitize' => null,
                ],
            ],
            
            // ==============================================
            // PROPERTIES GROUP - Container & Responsive
            // ==============================================
            'properties' => [
                // Container Width Settings
                'hvnly_container_width_xs' => [
                    'type' => 'string',
                    'default' => '100%',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_container_width_sm' => [
                    'type' => 'string',
                    'default' => '540px',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_container_width_md' => [
                    'type' => 'string',
                    'default' => '720px',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_container_width_lg' => [
                    'type' => 'string',
                    'default' => '960px',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_container_width_xl' => [
                    'type' => 'string',
                    'default' => '1140px',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_container_width_xxl' => [
                    'type' => 'string',
                    'default' => '1320px',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_container_width_xxxl' => [
                    'type' => 'string',
                    'default' => '1399px',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_container_width_4k' => [
                    'type' => 'string',
                    'default' => '1400px',
                    'sanitize' => 'sanitize_text_field',
                ],
                
                // Responsive View Settings
                'hvnly_propertyColumnsGapGrid' => [
                    'type' => 'string',
                    'default' => '10',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertyTabletView' => [
                    'type' => 'string',
                    'default' => '2',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertySmallTabletView' => [
                    'type' => 'string',
                    'default' => '2',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertyMobileTabletView' => [
                    'type' => 'string',
                    'default' => '1',
                    'sanitize' => 'sanitize_text_field',
                ],
            ],
            
            // ==============================================
            // PROPERTY DETAILS GROUP - Single Property Page
            // ==============================================
            'property-details' => [
                'hvnly_EnableBreadcrumbs' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_EnableBackToTop' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_EnablePrintButton' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_EnableSaveProperty' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
                'hvnly_EnableShareButton' => [
                    'type' => 'boolean',
                    'default' => true,
                    'sanitize' => 'rest_sanitize_boolean',
                ],
            ],
            
            // ==============================================
            // SHORTCODES GROUP
            // ==============================================
            'shortcodes' => [
                'hvnly_propertySearch' => [
                    'type' => 'string',
                    'default' => '[hvnly_property_search]',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertyGrid' => [
                    'type' => 'string',
                    'default' => '[hvnly_property_grid]',
                    'sanitize' => 'sanitize_text_field',
                ],
                'hvnly_propertyLists' => [
                    'type' => 'string',
                    'default' => '[hvnly_property_lists]',
                    'sanitize' => 'sanitize_text_field',
                ],
            ],
        ];
        
        return self::$schema;
    }
    

    
    /**
     * Get valid groups list
     *
     * @return array
     */
    public static function get_valid_groups()
    {
        return self::$valid_groups;
    }

    /**
     * Get valid map providers
     *
     * @return array
     */
    public static function get_map_providers()
    {
        return self::$map_providers;
    }

    /**
     * Get valid map styles
     *
     * @return array
     */
    public static function get_map_styles()
    {
        return self::$map_styles;
    }

    /**
     * Get valid Google map types
     *
     * @return array
     */
    public static function get_google_map_types()
    {
        return self::$google_map_types;
    }

    /**
     * Get zoom range (min, max)
     *
     * @return array
     */
    public static function get_zoom_range()
    {
        return self::$zoom_range;
    }

    /**
     * Validate map provider
     *
     * @param string $value Provider value
     * @return bool
     */
    public static function validate_map_provider($value)
    {
        return in_array($value, self::$map_providers, true);
    }

    /**
     * Validate map style
     *
     * @param string $value Map style value
     * @return bool
     */
    public static function validate_map_style($value)
    {
        return in_array($value, self::$map_styles, true);
    }

    /**
     * Validate Google map type
     *
     * @param string $value Google map type value
     * @return bool
     */
    public static function validate_google_map_type($value)
    {
        return in_array($value, self::$google_map_types, true);
    }

    /**
     * Validate coordinate (latitude or longitude)
     *
     * @param string $value Coordinate value
     * @return bool
     */
    public static function validate_coordinate($value)
    {
        if (!is_numeric($value)) {
            return false;
        }
        
        $coord = (float) $value;
        
        // Latitude range: -90 to 90, Longitude range: -180 to 180
        // We'll accept both and let the specific use case determine
        return $coord >= -180 && $coord <= 180;
    }

    /**
     * Validate zoom level
     *
     * @param int $value Zoom level
     * @return bool
     */
    public static function validate_zoom_level($value)
    {
        $value = absint($value);
        return $value >= self::$zoom_range['min'] && $value <= self::$zoom_range['max'];
    }
    
    /**
     * Validate and sanitize data for a specific group
     *
     * @param string $group Group name
     * @param array $data Data to validate
     * @return array Validated data
     */
    public static function validate_group($group, $data)
    {
        $schema = self::init_schema();
        
        if (!isset($schema[$group])) {
            return $data;
        }

        $validated_data = [];
        $schema_group = $schema[$group];

        foreach ($schema_group as $field => $field_schema) {
            $value = isset($data[$field]) ? $data[$field] : null;
            $validated_data[$field] = self::sanitize_field($value, $field_schema);
        }
        
        // Pass through any extra fields not in schema
        foreach ($data as $field => $value) {
            if (!isset($schema_group[$field])) {
                $validated_data[$field] = $value;
            }
        }

        return $validated_data;
    }
    
    /**
     * Sanitize a single field value
     *
     * @param mixed $value Field value
     * @param array $schema Field schema
     * @return mixed Sanitized value
     */
    public static function sanitize_field($value, $schema)
    {
        if (null === $value) {
            return isset($schema['default']) ? $schema['default'] : null;
        }

        if (isset($schema['type']) && !self::validate_type($value, $schema['type'])) {
            return isset($schema['default']) ? $schema['default'] : null;
        }

        // Apply custom validation if exists
        if (isset($schema['validate_callback']) && method_exists(__CLASS__, $schema['validate_callback'])) {
            if (!call_user_func([__CLASS__, $schema['validate_callback']], $value)) {
                return isset($schema['default']) ? $schema['default'] : null;
            }
        }

        if (isset($schema['sanitize']) && is_callable($schema['sanitize'])) {
            $value = call_user_func($schema['sanitize'], $value);
        } else {
            $value = self::default_sanitize_by_type($value, $schema['type'] ?? 'string');
        }

        return $value;
    }
    
    /**
     * Validate value type
     *
     * @param mixed $value Value to validate
     * @param string $type Expected type
     * @return bool
     */
    public static function validate_type($value, $type)
    {
        switch ($type) {
            case 'boolean':
                return is_bool($value) || in_array($value, [0, 1, '0', '1', 'true', 'false', true, false], true);
            case 'integer':
                return is_int($value) || ctype_digit((string) $value);
            case 'string':
                return is_string($value) || is_numeric($value);
            case 'array':
                return is_array($value);
            default:
                return true;
        }
    }
    
    /**
     * Default sanitization by type
     *
     * @param mixed $value Value to sanitize
     * @param string $type Value type
     * @return mixed
     */
    private static function default_sanitize_by_type($value, $type)
    {
        switch ($type) {
            case 'boolean':
                return filter_var($value, FILTER_VALIDATE_BOOLEAN);
            case 'integer':
                return absint($value);
            case 'string':
                return sanitize_text_field($value);
            case 'array':
                return is_array($value) ? $value : [];
            default:
                return sanitize_text_field($value);
        }
    }
    
    /**
     * Get default values for a specific group
     *
     * @param string $group Group name
     * @return array
     */
    public static function get_default_group($group)
    {
        $schema = self::init_schema();
        
        if (!isset($schema[$group])) {
            return [];
        }

        $defaults = [];
        foreach ($schema[$group] as $field => $field_schema) {
            $defaults[$field] = $field_schema['default'] ?? null;
        }
        
        return $defaults;
    }
    
    /**
     * Get all default values for all groups
     *
     * @return array
     */
    public static function get_all_defaults()
    {
        $schema = self::init_schema();
        $all_defaults = [];
        
        foreach (array_keys($schema) as $group) {
            $all_defaults[$group] = self::get_default_group($group);
        }
        
        return $all_defaults;
    }
    
    /**
     * Merge existing settings with defaults
     *
     * @param array $existing_settings Existing settings
     * @return array Merged settings
     */
    public static function merge_with_defaults($existing_settings)
    {
        $defaults = self::get_all_defaults();
        
        foreach ($defaults as $group => $group_defaults) {
            if (!isset($existing_settings[$group]) || !is_array($existing_settings[$group])) {
                $existing_settings[$group] = $group_defaults;
            } else {
                $existing_settings[$group] = array_merge($group_defaults, $existing_settings[$group]);
            }
        }
        
        return $existing_settings;
    }
}