<?php

/**
 * Settings REST API Controller
 *
 * Handles settings endpoints for all modules
 *
 * @package ProRank\SEO\Core\RestApi
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core\RestApi;

use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use ProRank\SEO\Core\SettingsManager;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}


/**
 * Settings controller class
 */


class SettingsController extends BaseController {
    
    /**
     * Rest base
     *
     * @var string
     */
    protected $rest_base = 'settings';
    
    /**
     * Settings manager instance
     *
     * @var SettingsManager|null
     */
    private ?SettingsManager $settings_manager = null;
    
    /**
     * Constructor
     *
     * @param SettingsManager $settings_manager Settings manager instance
     */
    public function __construct(SettingsManager $settings_manager) {
        parent::__construct();
        $this->settings_manager = $settings_manager;
    }

    /**
     * Permission callback for Pro+ settings endpoints that live in this controller.
     *
     * @return bool|WP_Error
     */
    public function check_pro_permission() {
        $request_method = function_exists( 'prorank_get_server_var' )
            ? strtoupper( prorank_get_server_var( 'REQUEST_METHOD' ) )
            : '';

        if ($request_method === 'OPTIONS') {
            return true;
        }

        if (!current_user_can('manage_options')) {
            return new WP_Error(
                'rest_forbidden',
                __('Sorry, you are not allowed to manage these settings.', 'prorank-seo'),
                ['status' => 403]
            );
        }

        $is_premium_active = defined('PRORANK_PREMIUM_VERSION')
            || (function_exists('is_plugin_active') && (
                is_plugin_active('prorank-seo-premium/prorank-seo.php')
                || is_plugin_active('prorank-seo-premium/prorank-seo-premium.php')
            ));

        if (!$is_premium_active) {
            return new WP_Error(
                'prorank_premium_required',
                __('ProRank SEO Premium plugin is required for this feature.', 'prorank-seo'),
                ['status' => 403]
            );
        }

        return true;
    }
    
    /**
     * Register routes
     *
     * @return void
     */
    public function register_routes(): void {
        
        // Site Basics endpoint
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/site_basics',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_site_basics'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_site_basics'],
                    'permission_callback' => [$this, 'check_permission'],
                    'args'                => [
                        'settings' => [
                            'required' => true,
                            'type'     => 'object',
                        ],
                    ],
                ],
            ]
        );
        
        // Breadcrumbs endpoint
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/breadcrumbs',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_breadcrumbs'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_breadcrumbs'],
                    'permission_callback' => [$this, 'check_permission'],
                    'args'                => [
                        'data' => [
                            'required' => false,
                            'type'     => 'object',
                        ],
                    ],
                ],
            ]
        );
        
        // Schema endpoints
        register_rest_route(
            'prorank-seo/v1',
            '/schemas',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_schemas'],
                    'permission_callback' => [$this, 'check_pro_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'create_schema'],
                    'permission_callback' => [$this, 'check_pro_permission'],
                ],
            ]
        );
        
        register_rest_route(
            'prorank-seo/v1',
            '/schemas/(?P<id>\d+)',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_schema'],
                    'permission_callback' => [$this, 'check_pro_permission'],
                ],
                [
                    'methods'             => 'PUT',
                    'callback'            => [$this, 'update_schema'],
                    'permission_callback' => [$this, 'check_pro_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::DELETABLE,
                    'callback'            => [$this, 'delete_schema'],
                    'permission_callback' => [$this, 'check_pro_permission'],
                ],
            ]
        );
        
        register_rest_route(
            'prorank-seo/v1',
            '/schemas/(?P<id>\d+)/toggle',
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [$this, 'toggle_schema_status'],
                'permission_callback' => [$this, 'check_pro_permission'],
            ]
        );
        
        register_rest_route(
            'prorank-seo/v1',
            '/schema/custom-fields',
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [$this, 'get_custom_fields'],
                'permission_callback' => [$this, 'check_pro_permission'],
            ]
        );
        
        // NOTE: Podcast settings endpoint is handled by PodcastModule.php
        // to avoid duplicate REST route registration

        // Titles & Meta endpoint
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/titles-meta',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_titles_meta'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_titles_meta'],
                    'permission_callback' => [$this, 'check_permission'],
                    'args'                => [
                        'settings' => [
                            'required' => false,
                            'type'     => 'object',
                        ],
                    ],
                ],
            ]
        );
        
        // Content Analysis endpoint
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/content-analysis',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_content_analysis'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_content_analysis'],
                    'permission_callback' => [$this, 'check_permission'],
                    'args'                => [
                        'data' => [
                            'required' => false,
                            'type'     => 'object',
                        ],
                    ],
                ],
            ]
        );

        // Backward-compatible alias for older admin bundles using underscore.
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/content_analysis',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_content_analysis'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_content_analysis'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
            ]
        );
        
        // Performance Beta toggle endpoint - use a unique path
        register_rest_route(
            $this->namespace,
            '/performance-beta',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_performance_beta'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_performance_beta'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
            ]
        );
        
        // Get all settings (admin only)
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base,
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_all_settings'],
                    'permission_callback' => function() {
                        // Allow read access for logged-in users
                        return is_user_logged_in();
                    },
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'save_all_settings'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
            ]
        );
        
        // Get settings for a specific group - register LAST as it's a catch-all
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/(?P<group>(?!(?:internal-linking|titles-meta|site_basics|site_info|breadcrumbs|content-analysis|basic-schema|performance-beta|hreflang|hreflang_quick|url-cleanup|image_optimization|sitemaps|robots_indexing|redirects|head_cleanup|head_cleanup_quick|html-sitemap|content-safeguard|database|snapshots)$)[a-zA-Z0-9_-]+)',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_settings'],
                    'permission_callback' => [$this, 'check_permission'],
                    'args'                => [
                        'group' => [
                            'required'          => true,
                            'sanitize_callback' => 'sanitize_key',
                            'validate_callback' => function($param) {
                                return !empty($param);
                            },
                        ],
                    ],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_settings'],
                    'permission_callback' => [$this, 'check_permission'],
                    'args'                => [
                        'group' => [
                            'required'          => true,
                            'sanitize_callback' => 'sanitize_key',
                        ],
                        'settings' => [
                            'required'          => false,
                            'type'              => 'object',
                        ],
                    ],
                ],
            ]
        );
    }
    
    /**
     * Get settings for a specific group
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_settings(WP_REST_Request $request) {
        // Sanitize settings group parameter
        $group = sanitize_key($request->get_param('group'));
        
        if (!$this->settings_manager) {
            return $this->get_error_response(
                __('Settings manager not available', 'prorank-seo'),
                500
            );
        }
        
        try {
            if ($group === 'advanced') {
                return rest_ensure_response([
                    'group' => $group,
                    'settings' => wp_parse_args(
                        get_option('prorank_seo_advanced_settings', []),
                        $this->get_advanced_settings_defaults()
                    ),
                ]);
            }

            $settings = $this->settings_manager->get_settings($group);
            
            return rest_ensure_response([
                'group' => $group,
                'settings' => $settings,
            ]);
            
        } catch (\Exception $e) {
            return $this->get_error_response(
/* translators: %1$: value */
                sprintf(__('Failed to get settings: %1$s', 'prorank-seo'), $e->getMessage()),
                500
            );
        }
    }
    
    /**
     * Update settings for a specific group
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_settings(WP_REST_Request $request) {
        // Sanitize settings group parameter
        $group = sanitize_key($request->get_param('group'));

        $settings = $request->get_param('settings'); // Sanitized by validate_settings()

        // Some admin screens POST settings directly at root-level instead of nested under "settings".
        if (!is_array($settings)) {
            $json_params = $request->get_json_params();
            if (is_array($json_params)) {
                $settings = $json_params;
            } else {
                $settings = $request->get_body_params();
            }
        }

        if (!is_array($settings)) {
            $settings = [];
        }
        
        if (!$this->settings_manager) {
            return $this->get_error_response(
                __('Settings manager not available', 'prorank-seo'),
                500
            );
        }
        
        // Validate settings based on group
        $validated_settings = $this->validate_settings($group, $settings);
        if (is_wp_error($validated_settings)) {
            return $validated_settings;
        }
        
        try {
            if ($group === 'advanced') {
                $existing = get_option('prorank_seo_advanced_settings', []);
                if (!is_array($existing)) {
                    $existing = [];
                }

                $merged = array_merge(
                    $this->get_advanced_settings_defaults(),
                    $existing,
                    $validated_settings
                );

                update_option('prorank_seo_advanced_settings', $merged);

                return rest_ensure_response([
                    'success' => true,
                    'message' => __('Settings saved successfully', 'prorank-seo'),
                    'group' => $group,
                    'settings' => $merged,
                ]);
            }

            // Update settings
            foreach ($validated_settings as $key => $value) {
                // Check if the key already has the group prefix
                if (strpos($key, $group . '_') === 0) {
                    // Key already has prefix, use update() directly
                    $this->settings_manager->update($key, $value);
                } else {
                    // Key doesn't have prefix, use update_setting()
                    $this->settings_manager->update_setting($group, $key, $value);
                }
            }

            if ($group === 'site-audit') {
                $this->sync_site_audit_runtime_settings($validated_settings);
            }
            
            // Trigger action after settings update
            do_action('prorank_seo_settings_updated', $group, $validated_settings);
            
            return rest_ensure_response([
                'success' => true,
                'message' => __('Settings saved successfully', 'prorank-seo'),
                'group' => $group,
                'settings' => $this->settings_manager->get_settings($group),
            ]);
            
        } catch (\Exception $e) {
            return $this->get_error_response(
/* translators: %1$: value */
                sprintf(__('Failed to save settings: %1$s', 'prorank-seo'), $e->getMessage()),
                500
            );
        }
    }
    
    /**
     * Get all settings (for export/debug)
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_all_settings(WP_REST_Request $request) {
        if (!$this->settings_manager) {
            return $this->get_error_response(
                __('Settings manager not available', 'prorank-seo'),
                500
            );
        }
        
        try {
            $all_settings = [];
            
            // Get all registered setting groups
            $groups = $this->get_setting_groups();
            
            foreach ($groups as $group) {
                try {
                    if ($group === 'advanced') {
                        $all_settings[$group] = wp_parse_args(
                            get_option('prorank_seo_advanced_settings', []),
                            $this->get_advanced_settings_defaults()
                        );
                    } else {
                        $all_settings[$group] = $this->settings_manager->get_settings($group);
                    }
                } catch (\Exception $e) {
                    // If settings don't exist for this group, use empty array
                    $all_settings[$group] = [];
                }
            }
            
            return rest_ensure_response($all_settings);
            
        } catch (\Exception $e) {
            return $this->get_error_response(
/* translators: %1$: value */
                sprintf(__('Failed to get all settings: %1$s', 'prorank-seo'), $e->getMessage()),
                500
            );
        }
    }
    
    /**
     * Save all settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function save_all_settings(WP_REST_Request $request) {
        if (!$this->settings_manager) {
            return $this->get_error_response(
                __('Settings manager not available', 'prorank-seo'),
                500
            );
        }
        
        $settings = $request->get_json_params();
        
        if (!is_array($settings)) {
            return $this->get_error_response(
                __('Invalid settings format', 'prorank-seo'),
                400
            );
        }
        
        try {
            foreach ($settings as $group => $group_settings) {
                if (!is_array($group_settings)) {
                    continue;
                }
                
                $validated_settings = $this->validate_settings($group, $group_settings);
                if (is_wp_error($validated_settings)) {
                    return $validated_settings;
                }
                
                if ($group === 'advanced') {
                    $existing = get_option('prorank_seo_advanced_settings', []);
                    if (!is_array($existing)) {
                        $existing = [];
                    }

                    $merged = array_merge(
                        $this->get_advanced_settings_defaults(),
                        $existing,
                        $validated_settings
                    );

                    update_option('prorank_seo_advanced_settings', $merged);
                    continue;
                }

                foreach ($validated_settings as $key => $value) {
                    $this->settings_manager->update_setting($group, $key, $value);
                }
            }
            
            return rest_ensure_response([
                'success' => true,
                'message' => __('Settings saved successfully', 'prorank-seo'),
            ]);
            
        } catch (\Exception $e) {
            return $this->get_error_response(
/* translators: %1$: value */
                sprintf(__('Failed to save settings: %1$s', 'prorank-seo'), $e->getMessage()),
                500
            );
        }
    }
    
    /**
     * Validate settings based on group
     *
     * @param string $group    Settings group
     * @param array  $settings Settings to validate
     * @return array|WP_Error Validated settings or error
     */
    private function validate_settings(string $group, array $settings) {
        $validated = [];
        
        // Group-specific validation
        switch ($group) {
            case 'sitemaps':
                $validated = $this->validate_sitemap_settings($settings);
                break;
                
            case 'redirects':
                $validated = $this->validate_redirect_settings($settings);
                break;
                
            case 'meta':
                $validated = $this->validate_meta_settings($settings);
                break;
                
            case 'social':
                $validated = $this->validate_social_settings($settings);
                break;
                
            case 'cache':
                $validated = $this->validate_cache_settings($settings);
                break;

            case 'advanced':
                $validated = $this->validate_advanced_settings($settings);
                break;
                
            case 'image_optimization':
                $validated = $this->validate_image_optimization_settings($settings);
                break;
                
            case 'asset_optimization':
                $validated = $this->validate_asset_optimization_settings($settings);
                break;
                
            case 'site_audit':
                $validated = $this->validate_site_audit_settings($settings);
                break;

            case 'psi':
            case 'psi_api':
                $validated = $this->validate_psi_settings($settings);
                break;
                
            case 'clarity':
                $validated = $this->validate_clarity_settings($settings);
                break;

            case 'bing_webmaster':
                $validated = $this->validate_bing_webmaster_settings($settings);
                break;
                
            default:
                // For unknown groups, pass through with basic sanitization
                foreach ($settings as $key => $value) {
                    $key = sanitize_key($key);
                    
                    if (is_string($value)) {
                        $validated[$key] = sanitize_text_field($value);
                    } elseif (is_bool($value)) {
                        $validated[$key] = (bool) $value;
                    } elseif (is_numeric($value)) {
                        $validated[$key] = is_float($value) ? (float) $value : (int) $value;
                    } elseif (is_array($value)) {
                        $validated[$key] = array_map('sanitize_text_field', $value);
                    } else {
                        $validated[$key] = $value;
                    }
                }
        }
        
        return $validated;
    }

    /**
     * Validate advanced settings.
     *
     * @param array $settings Settings to validate
     * @return array
     */
    private function validate_advanced_settings(array $settings): array {
        $validated = [];

        $boolean_fields = [
            'debug_mode',
            'disable_emojis',
            'disable_gutenberg',
            'disable_xmlrpc',
            'disable_rest_api_public',
            'remove_version_strings',
            'disable_file_editing',
        ];

        foreach ($boolean_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = (bool) $settings[$field];
            }
        }

        if (isset($settings['api_timeout'])) {
            $validated['api_timeout'] = min(120, max(5, (int) $settings['api_timeout']));
        }

        if (isset($settings['cache_duration'])) {
            $validated['cache_duration'] = min(86400, max(60, (int) $settings['cache_duration']));
        }

        if (isset($settings['log_level'])) {
            $allowed_levels = ['error', 'warning', 'info', 'debug'];
            $level = sanitize_key((string) $settings['log_level']);
            $validated['log_level'] = in_array($level, $allowed_levels, true) ? $level : 'error';
        }

        return $validated;
    }
    
    /**
     * Validate sitemap settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_sitemap_settings(array $settings): array {
        $validated = [];
        
        // Boolean settings
        $boolean_fields = [
            'enable_xml_sitemap',
            'exclude_empty_terms',
            'include_images',
            'include_author_archives',
            'exclude_noindex',
            'ping_search_engines',
        ];
        
        foreach ($boolean_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = (bool) $settings[$field];
            }
        }
        
        // Integer settings
        if (isset($settings['posts_per_sitemap'])) {
            $validated['posts_per_sitemap'] = min(50000, max(1, (int) $settings['posts_per_sitemap']));
        }
        
        // Array settings
        if (isset($settings['include_post_types']) && is_array($settings['include_post_types'])) {
            $validated['include_post_types'] = array_map('sanitize_key', $settings['include_post_types']);
        }
        
        if (isset($settings['include_taxonomies']) && is_array($settings['include_taxonomies'])) {
            $validated['include_taxonomies'] = array_map('sanitize_key', $settings['include_taxonomies']);
        }
        
        if (isset($settings['author_roles']) && is_array($settings['author_roles'])) {
            $validated['author_roles'] = array_map('sanitize_key', $settings['author_roles']);
        }
        
        // String settings
        if (isset($settings['sitemap_index_url'])) {
            $url = sanitize_file_name($settings['sitemap_index_url']);
            if (preg_match('/^[a-zA-Z0-9_-]+\.xml$/', $url)) {
                $validated['sitemap_index_url'] = $url;
            }
        }
        
        return $validated;
    }
    
    /**
     * Validate redirect settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_redirect_settings(array $settings): array {
        $validated = [];

        // Validate source URL
        if (isset($settings['source']) || isset($settings['source_url'])) {
            $source = $settings['source'] ?? $settings['source_url'] ?? '';
            $validated['source_url'] = sanitize_text_field(wp_unslash($source));
        }

        // Validate target URL
        if (isset($settings['target']) || isset($settings['target_url'])) {
            $target = $settings['target'] ?? $settings['target_url'] ?? '';
            $validated['target_url'] = esc_url_raw(wp_unslash($target));
        }

        // Validate redirect type
        $valid_types = ['301', '302', '307', '308', '410', '451'];
        if (isset($settings['type']) || isset($settings['redirect_type'])) {
            $type = (string) ($settings['type'] ?? $settings['redirect_type'] ?? '301');
            $validated['redirect_type'] = in_array($type, $valid_types, true) ? $type : '301';
        }

        // Validate enabled status
        if (isset($settings['enabled'])) {
            $validated['enabled'] = (bool) $settings['enabled'];
        }

        // Validate regex flag
        if (isset($settings['is_regex'])) {
            $validated['is_regex'] = (bool) $settings['is_regex'];
        }

        // Validate case sensitivity
        if (isset($settings['case_insensitive'])) {
            $validated['case_insensitive'] = (bool) $settings['case_insensitive'];
        }

        return $validated;
    }

    /**
     * Validate meta settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_meta_settings(array $settings): array {
        $validated = [];

        foreach ($settings as $key => $value) {
            $sanitized_key = sanitize_key($key);

            // Title fields
            if (str_starts_with($sanitized_key, 'title_') || str_ends_with($sanitized_key, '_title')) {
                $validated[$sanitized_key] = sanitize_text_field(wp_unslash($value));
            }
            // Description fields
            elseif (str_starts_with($sanitized_key, 'description_') ||
                    str_starts_with($sanitized_key, 'desc_') ||
                    str_ends_with($sanitized_key, '_description') ||
                    str_ends_with($sanitized_key, '_desc')) {
                $validated[$sanitized_key] = sanitize_textarea_field(wp_unslash($value));
            }
            // Boolean toggle fields
            elseif (str_starts_with($sanitized_key, 'enable_') ||
                    str_starts_with($sanitized_key, 'disable_') ||
                    str_starts_with($sanitized_key, 'show_') ||
                    str_starts_with($sanitized_key, 'hide_') ||
                    str_ends_with($sanitized_key, '_enabled') ||
                    str_ends_with($sanitized_key, '_noindex') ||
                    str_ends_with($sanitized_key, '_nofollow')) {
                $validated[$sanitized_key] = (bool) $value;
            }
            // Separator field
            elseif ($sanitized_key === 'title_separator' || $sanitized_key === 'separator') {
                $allowed_separators = ['-', '–', '—', ':', '·', '•', '*', '|', '~', '/'];
                $separator = sanitize_text_field($value);
                $validated[$sanitized_key] = in_array($separator, $allowed_separators, true) ? $separator : '-';
            }
            // Integer fields
            elseif (str_ends_with($sanitized_key, '_length') || str_ends_with($sanitized_key, '_limit')) {
                $validated[$sanitized_key] = absint($value);
            }
            // Default: sanitize as text
            else {
                if (is_array($value)) {
                    $validated[$sanitized_key] = array_map('sanitize_text_field', $value);
                } elseif (is_bool($value)) {
                    $validated[$sanitized_key] = $value;
                } else {
                    $validated[$sanitized_key] = sanitize_text_field(wp_unslash($value));
                }
            }
        }

        return $validated;
    }

    /**
     * Validate social settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_social_settings(array $settings): array {
        $validated = [];

        // URL fields that need URL validation
        $url_fields = [
            'facebook_url',
            'facebook_page_url',
            'twitter_url',
            'linkedin_url',
            'instagram_url',
            'youtube_url',
            'pinterest_url',
            'tiktok_url',
            'default_og_image',
            'default_twitter_image',
        ];

        // Username fields that need specific sanitization
        $username_fields = [
            'twitter_username',
            'facebook_admin_id',
            'facebook_app_id',
        ];

        foreach ($settings as $key => $value) {
            $sanitized_key = sanitize_key($key);

            if (in_array($sanitized_key, $url_fields, true)) {
                $validated[$sanitized_key] = esc_url_raw(wp_unslash($value));
            } elseif (in_array($sanitized_key, $username_fields, true)) {
                // Remove @ from usernames and sanitize
                $username = sanitize_text_field(wp_unslash($value));
                $validated[$sanitized_key] = ltrim($username, '@');
            } elseif (str_starts_with($sanitized_key, 'enable_') || str_ends_with($sanitized_key, '_enabled')) {
                $validated[$sanitized_key] = (bool) $value;
            } elseif ($sanitized_key === 'og_type' || $sanitized_key === 'twitter_card_type') {
                $allowed_og_types = ['website', 'article', 'product', 'profile'];
                $allowed_twitter_types = ['summary', 'summary_large_image', 'app', 'player'];

                if ($sanitized_key === 'og_type') {
                    $validated[$sanitized_key] = in_array($value, $allowed_og_types, true) ? $value : 'website';
                } else {
                    $validated[$sanitized_key] = in_array($value, $allowed_twitter_types, true) ? $value : 'summary_large_image';
                }
            } else {
                $validated[$sanitized_key] = sanitize_text_field(wp_unslash($value));
            }
        }

        return $validated;
    }
    
    /**
     * Get all setting groups
     *
     * @return array List of setting groups
     */
    private function get_setting_groups(): array {
        return [
            'general',
            'sitemaps',
            'redirects',
            'meta',
            'social',
            'schema',
            'performance',
            'cache',
            'analytics',
            'tools',
            'advanced',
        ];
    }

    /**
     * Get advanced settings defaults.
     *
     * @return array
     */
    private function get_advanced_settings_defaults(): array {
        return [
            'debug_mode' => false,
            'disable_emojis' => false,
            'disable_gutenberg' => false,
            'disable_xmlrpc' => true,
            'disable_rest_api_public' => false,
            'remove_version_strings' => true,
            'disable_file_editing' => true,
            'api_timeout' => 30,
            'cache_duration' => 3600,
            'log_level' => 'error',
        ];
    }
    
    /**
     * Validate cache settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_cache_settings(array $settings): array {
        $validated = [];
        
        // Boolean settings
        $boolean_fields = [
            'cache_enabled',
            'cache_gzip',
            'cache_mobile_separate',
            'preload_enabled',
            'preload_auto_save',
            'js_defer',
            'js_delay',
            'js_combine',
            'css_minify',
            'css_combine',
            'css_async',
        ];
        
        foreach ($boolean_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = (bool) $settings[$field];
            }
        }
        
        // Integer settings
        if (isset($settings['cache_lifetime'])) {
            $validated['cache_lifetime'] = min(86400, max(60, (int) $settings['cache_lifetime']));
        }
        
        // String settings
        $string_fields = [
            'cache_exclude_urls',
            'cache_exclude_cookies',
            'cache_exclude_agents',
            'js_exclude',
            'css_exclude',
        ];
        
        foreach ($string_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = sanitize_textarea_field($settings[$field]);
            }
        }
        
        // Select fields
        if (isset($settings['preload_mode'])) {
            $allowed = ['sitemap', 'recent'];
            $validated['preload_mode'] = in_array($settings['preload_mode'], $allowed) 
                ? $settings['preload_mode'] 
                : 'sitemap';
        }
        
        if (isset($settings['preload_schedule'])) {
            $allowed = ['hourly', 'daily', 'weekly'];
            $validated['preload_schedule'] = in_array($settings['preload_schedule'], $allowed) 
                ? $settings['preload_schedule'] 
                : 'daily';
        }
        
        return $validated;
    }
    
    
    /**
     * Validate image optimization settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_image_optimization_settings(array $settings): array {
        $validated = [];
        
        // Boolean settings
        $boolean_fields = [
            'lazyload_images',
            'lazyload_iframes',
            'lazyload_videos',
            'lazyload_background_images',
            'image_opt_webp_enabled',
            'image_opt_avif_enabled',
            'image_opt_delivery_enabled',
        ];
        
        foreach ($boolean_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = (bool) $settings[$field];
            }
        }
        
        // Integer settings
        if (isset($settings['image_opt_quality_webp'])) {
            $validated['image_opt_quality_webp'] = min(100, max(1, (int) $settings['image_opt_quality_webp']));
        }
        
        if (isset($settings['image_opt_quality_avif'])) {
            $validated['image_opt_quality_avif'] = min(100, max(1, (int) $settings['image_opt_quality_avif']));
        }
        
        // String settings
        if (isset($settings['lazyload_exclude'])) {
            $validated['lazyload_exclude'] = sanitize_textarea_field($settings['lazyload_exclude']);
        }
        
        return $validated;
    }
    
    /**
     * Validate asset optimization settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_asset_optimization_settings(array $settings): array {
        $validated = [];
        
        // Boolean settings
        $boolean_fields = [
            'critical_css_enabled',
            'critical_css_async',
            'critical_css_preload',
            'unused_css_enabled',
            'unused_css_collect',
            'unused_css_minify',
            'minify_html',
            'remove_html_comments',
            'js_advanced_enabled',
            'font_opt_google_local',
            'font_opt_display_swap',
            'font_opt_subset',
        ];
        
        foreach ($boolean_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = (bool) $settings[$field];
            }
        }
        
        // String settings
        $string_fields = [
            'critical_css_mode',
            'critical_css_manual',
            'critical_css_exclude',
            'unused_css_exclude',
            'unused_css_exclude_files',
        ];
        
        foreach ($string_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = sanitize_textarea_field($settings[$field]);
            }
        }
        
        // Select fields
        if (isset($settings['critical_css_mode'])) {
            $allowed = ['manual', 'automatic'];
            $validated['critical_css_mode'] = in_array($settings['critical_css_mode'], $allowed) 
                ? $settings['critical_css_mode'] 
                : 'manual';
        }
        
        // Array fields
        if (isset($settings['js_advanced_rules']) && is_array($settings['js_advanced_rules'])) {
            $validated['js_advanced_rules'] = array_map(function($rule) {
                return [
                    'handle' => sanitize_key($rule['handle'] ?? ''),
                    'action' => in_array($rule['action'] ?? '', ['defer', 'delay', 'remove']) ? $rule['action'] : 'defer',
                ];
            }, $settings['js_advanced_rules']);
        }
        
        return $validated;
    }
    
    /**
     * Get performance beta setting
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_performance_beta(WP_REST_Request $request) {
        if (!$this->settings_manager) {
            return new \WP_Error(
                'no_settings_manager',
                __('Settings manager not available', 'prorank-seo'),
                ['status' => 500]
            );
        }
        
        try {
            // Get performance beta setting from general settings
            $value = $this->settings_manager->get('general', 'performance_beta', false);
            
            return rest_ensure_response([
                'value' => (bool) $value,
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'settings_error',
                $e->getMessage(),
                ['status' => 500]
            );
        }
    }
    
    /**
     * Update performance beta setting
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_performance_beta(WP_REST_Request $request) {
        if (!$this->settings_manager) {
            return new \WP_Error(
                'no_settings_manager',
                __('Settings manager not available', 'prorank-seo'),
                ['status' => 500]
            );
        }
        
        // Get value from request body or params
        $body = $request->get_json_params();
        $value = isset($body['value']) ? $body['value'] : $request->get_param('value');
        
        // Convert to boolean
        $bool_value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
        if ($bool_value === null) {
            return new \WP_Error(
                'invalid_value',
                __('Invalid boolean value', 'prorank-seo'),
                ['status' => 400]
            );
        }
        
        try {
            // Update performance beta setting in general settings
            $this->settings_manager->update_setting('general', 'performance_beta', $bool_value);
            
            // Trigger action after update
            do_action('prorank_seo_performance_beta_updated', $bool_value);
            
            return rest_ensure_response([
                'success' => true,
                'message' => $bool_value 
                    ? __('Performance Beta enabled', 'prorank-seo')
                    : __('Performance Beta disabled', 'prorank-seo'),
                'value' => $bool_value,
            ]);
            
        } catch (\Exception $e) {
            return new \WP_Error(
                'update_error',
/* translators: %1$: value */
                sprintf(__('Failed to update performance beta: %1$s', 'prorank-seo'), $e->getMessage()),
                ['status' => 500]
            );
        }
    }
    
    /**
     * Validate site audit settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_site_audit_settings(array $settings): array {
        $validated = [];
        
        // Boolean settings
        $boolean_fields = [
            'site_audit_schedule_enabled',
            'site_audit_auto_fix_enabled',
            'site_audit_auto_fix_require_approval',
            'white_label_remove_branding',
            'site_audit_email_reports',
            'schedule_enabled',
            'email_notifications',
            'email_critical_only',
            'enable_autofix',
            'autofix_trailing_slashes',
            'autofix_transients',
            'autofix_database',
            'autofix_mixed_content',
            'autofix_meta_descriptions',
            'autofix_alt_texts',
            'autofix_compression',
            'autofix_caching',
        ];
        
        foreach ($boolean_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = (bool) $settings[$field];
            }
        }
        
        // String settings
        $string_fields = [
            'site_audit_schedule_frequency',
            'white_label_logo',
            'white_label_company_name',
            'white_label_primary_color',
            'white_label_secondary_color',
            'google_pagespeed_api_key',
            'site_audit_email_recipients',
            'schedule_frequency',
            'schedule_time',
            'notification_emails',
        ];
        
        foreach ($string_fields as $field) {
            if (isset($settings[$field])) {
                $validated[$field] = sanitize_text_field($settings[$field]);
            }
        }
        
        // Integer settings
        if (isset($settings['site_audit_max_urls'])) {
            $validated['site_audit_max_urls'] = min(5000, max(50, (int) $settings['site_audit_max_urls']));
        }
        
        if (isset($settings['site_audit_max_depth'])) {
            $validated['site_audit_max_depth'] = min(10, max(1, (int) $settings['site_audit_max_depth']));
        }

        if (isset($settings['max_urls'])) {
            $validated['max_urls'] = min(10000, max(10, (int) $settings['max_urls']));
        }

        if (isset($settings['max_depth'])) {
            $validated['max_depth'] = min(10, max(1, (int) $settings['max_depth']));
        }
        
        // Array settings
        if (isset($settings['site_audit_check_types']) && is_array($settings['site_audit_check_types'])) {
            $validated['site_audit_check_types'] = $this->sanitize_site_audit_check_types($settings['site_audit_check_types']);
        }

        if (isset($settings['check_types']) && is_array($settings['check_types'])) {
            $validated['check_types'] = $this->sanitize_site_audit_check_types($settings['check_types']);
        }
        
        if (isset($settings['site_audit_auto_fix_types']) && is_array($settings['site_audit_auto_fix_types'])) {
            $validated['site_audit_auto_fix_types'] = array_map('sanitize_key', $settings['site_audit_auto_fix_types']);
        }
        
        return $validated;
    }

    /**
     * Normalize site audit check map to key => bool.
     *
     * @param array $check_types Raw check types payload.
     * @return array
     */
    private function sanitize_site_audit_check_types(array $check_types): array {
        $clean = [];

        foreach ($check_types as $key => $value) {
            if (is_int($key)) {
                $check_key = sanitize_key((string) $value);
                if ($check_key !== '') {
                    $clean[$check_key] = true;
                }
                continue;
            }

            $check_key = sanitize_key((string) $key);
            if ($check_key === '') {
                continue;
            }
            $clean[$check_key] = (bool) $value;
        }

        return $clean;
    }

    /**
     * Keep legacy Site Audit runtime options in sync with settings payload.
     *
     * @param array $settings Validated settings payload.
     * @return void
     */
    private function sync_site_audit_runtime_settings(array $settings): void {
        $schedule_changed = false;
        $max_urls = $settings['max_urls'] ?? $settings['site_audit_max_urls'] ?? null;
        $max_depth = $settings['max_depth'] ?? $settings['site_audit_max_depth'] ?? null;
        $check_types = $settings['check_types'] ?? $settings['site_audit_check_types'] ?? null;
        $schedule_enabled = $settings['schedule_enabled'] ?? $settings['site_audit_schedule_enabled'] ?? null;
        $schedule_frequency = $settings['schedule_frequency'] ?? $settings['site_audit_schedule_frequency'] ?? null;
        $schedule_time = $settings['schedule_time'] ?? null;
        $email_notifications = $settings['email_notifications'] ?? $settings['site_audit_email_reports'] ?? null;
        $email_critical_only = $settings['email_critical_only'] ?? null;
        $notification_emails = $settings['notification_emails'] ?? $settings['site_audit_email_recipients'] ?? null;
        $enable_autofix = $settings['enable_autofix'] ?? $settings['site_audit_auto_fix_enabled'] ?? null;

        if ($max_urls !== null) {
            $max_urls = min(10000, max(10, (int) $max_urls));
            update_option('prorank_audit_max_urls', $max_urls);
        }

        if ($max_depth !== null) {
            $max_depth = min(10, max(1, (int) $max_depth));
            update_option('prorank_audit_max_depth', $max_depth);
        }

        if (is_array($check_types)) {
            update_option('prorank_audit_check_types', $this->sanitize_site_audit_check_types($check_types));
        }

        if ($schedule_enabled !== null) {
            update_option('prorank_audit_schedule_enabled', (bool) $schedule_enabled);
            $schedule_changed = true;
        }

        if ($schedule_frequency !== null) {
            $allowed = ['daily', 'weekly', 'biweekly', 'monthly'];
            $value = sanitize_key((string) $schedule_frequency);
            update_option('prorank_audit_schedule_frequency', in_array($value, $allowed, true) ? $value : 'weekly');
            $schedule_changed = true;
        }

        if ($schedule_time !== null) {
            $time_value = preg_match('/^(?:[01]\d|2[0-3]):[0-5]\d$/', (string) $schedule_time)
                ? (string) $schedule_time
                : '02:00';
            update_option('prorank_audit_schedule_time', $time_value);
            $schedule_changed = true;
        }

        if ($email_notifications !== null) {
            update_option('prorank_audit_email_notifications', (bool) $email_notifications);
        }

        if ($email_critical_only !== null) {
            update_option('prorank_audit_email_critical_only', (bool) $email_critical_only);
        }

        if ($notification_emails !== null) {
            update_option('prorank_audit_notification_emails', sanitize_text_field((string) $notification_emails));
        }

        if ($enable_autofix !== null) {
            update_option('prorank_audit_enable_autofix', (bool) $enable_autofix);
        }

        $autofix_keys = [
            'autofix_trailing_slashes',
            'autofix_transients',
            'autofix_database',
            'autofix_mixed_content',
            'autofix_meta_descriptions',
            'autofix_alt_texts',
            'autofix_compression',
            'autofix_caching',
        ];

        foreach ($autofix_keys as $autofix_key) {
            if (array_key_exists($autofix_key, $settings)) {
                update_option('prorank_audit_' . $autofix_key, (bool) $settings[$autofix_key]);
            }
        }

        $runtime_settings = get_option('prorank_audit_settings', []);
        if (!is_array($runtime_settings)) {
            $runtime_settings = [];
        }

        if ($max_urls !== null) {
            $runtime_settings['max_urls'] = $max_urls;
            $runtime_settings['max_pages'] = $max_urls;
        }

        if ($max_depth !== null) {
            $runtime_settings['max_depth'] = $max_depth;
        }

        if (is_array($check_types)) {
            $runtime_settings['check_types'] = $this->sanitize_site_audit_check_types($check_types);
        }

        update_option('prorank_audit_settings', $runtime_settings);

        if ($schedule_changed) {
            $this->reschedule_site_audit_cron();
        }
    }

    /**
     * Apply site audit schedule changes immediately after settings save.
     *
     * @return void
     */
    private function reschedule_site_audit_cron(): void {
        $hook = 'prorank_audit_scheduled_run';
        $enabled = (bool) get_option('prorank_audit_schedule_enabled', false);
        $frequency = sanitize_key((string) get_option('prorank_audit_schedule_frequency', 'weekly'));
        $schedule_time = (string) get_option('prorank_audit_schedule_time', '02:00');
        if (!preg_match('/^(?:[01]\d|2[0-3]):[0-5]\d$/', $schedule_time)) {
            $schedule_time = '02:00';
        }

        $recurrence_map = [
            'daily' => 'daily',
            'weekly' => 'weekly',
            'biweekly' => 'prorank_biweekly',
            'monthly' => 'monthly',
        ];
        $recurrence = $recurrence_map[$frequency] ?? 'weekly';

        add_filter('cron_schedules', static function(array $schedules): array {
            if (!isset($schedules['prorank_biweekly'])) {
                $schedules['prorank_biweekly'] = [
                    'interval' => 14 * DAY_IN_SECONDS,
                    'display' => __('Every Two Weeks', 'prorank-seo'),
                ];
            }
            if (!isset($schedules['monthly'])) {
                $schedules['monthly'] = [
                    'interval' => 30 * DAY_IN_SECONDS,
                    'display' => __('Once Monthly', 'prorank-seo'),
                ];
            }
            return $schedules;
        });

        $schedules = wp_get_schedules();
        if (!isset($schedules[$recurrence])) {
            $recurrence = $frequency === 'daily' ? 'daily' : 'weekly';
        }

        wp_clear_scheduled_hook($hook);
        if (!$enabled) {
            return;
        }

        try {
            $timezone = wp_timezone();
            $now = new \DateTimeImmutable('now', $timezone);
            [$hour, $minute] = array_map('intval', explode(':', $schedule_time));
            $next = $now->setTime($hour, $minute, 0);
            if ($next <= $now) {
                $next = $next->modify('+1 day');
            }
            wp_schedule_event($next->getTimestamp(), $recurrence, $hook);
        } catch (\Throwable $e) {
            wp_schedule_event(time() + HOUR_IN_SECONDS, $recurrence, $hook);
        }
    }

    /**
     * Validate PSI settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_psi_settings(array $settings): array {
        $validated = [];
        
        // API key
        if (isset($settings['api_key'])) {
            $api_key = sanitize_text_field($settings['api_key']);
            // Basic validation for Google API key format
            if (empty($api_key) || preg_match('/^AIza[0-9A-Za-z_-]{35}$/', $api_key)) {
                $validated['api_key'] = $api_key;
            }
        }
        
        // Auto-track setting
        if (isset($settings['auto_track'])) {
            $validated['auto_track'] = (bool) $settings['auto_track'];
        }
        
        // Track frequency
        if (isset($settings['track_frequency'])) {
            $validated['track_frequency'] = in_array($settings['track_frequency'], ['daily', 'weekly', 'monthly']) 
                ? $settings['track_frequency'] 
                : 'weekly';
        }
        
        return $validated;
    }
    
    /**
     * Validate Clarity settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_clarity_settings(array $settings): array {
        $validated = [];
        
        // Enabled flag
        if (isset($settings['enabled'])) {
            $validated['enabled'] = (bool) $settings['enabled'];
        }
        
        // Project ID
        if (isset($settings['project_id'])) {
            $project_id = sanitize_text_field($settings['project_id']);
            // Basic validation for Clarity project ID format
            if (preg_match('/^[a-z0-9]{8,12}$/', $project_id) || empty($project_id)) {
                $validated['project_id'] = $project_id;
            }
        }
        
        return $validated;
    }

    /**
     * Validate Bing Webmaster Tools settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_bing_webmaster_settings(array $settings): array {
        $validated = [];

        if (isset($settings['api_key'])) {
            $validated['api_key'] = sanitize_text_field($settings['api_key']);
        }

        if (isset($settings['site_url'])) {
            $validated['site_url'] = esc_url_raw($settings['site_url']);
        }

        return $validated;
    }
    
    /**
     * Get site basics settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_site_basics(WP_REST_Request $request) {
        $settings = get_option('prorank_seo_site_basics', []);
        if (!is_array($settings)) {
            $settings = [];
        }

        $settings = $this->normalize_site_basics_settings($settings);
        $settings = wp_parse_args($settings, $this->get_site_basics_defaults());
        $settings = $this->hydrate_site_basics_from_legacy_options($settings);
        
        return rest_ensure_response([
            'success' => true,
            'settings' => $settings,
        ]);
    }
    
    /**
     * Update site basics settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_site_basics(WP_REST_Request $request) {
        $settings = $request->get_param('settings');
        
        if (!is_array($settings)) {
            return $this->get_error_response(
                __('Invalid settings format', 'prorank-seo'),
                400
            );
        }

        $settings = $this->normalize_site_basics_settings($settings);
        
        // Sanitize settings
        $sanitized = [];
        $text_fields = [
            'site_name', 'site_alternate_name', 'site_tagline', 'title_separator',
            'site_logo', 'site_image', 'person_logo', 'google_verification', 'bing_verification',
            'baidu_verification', 'yandex_verification', 'pinterest_verification',
            'norton_verification', 'facebook_page_url', 'facebook_authorship',
            'facebook_admin_id', 'facebook_app_id', 'facebook_secret',
            'twitter_username', 'linkedin_url', 'instagram_url', 'youtube_url',
            'pinterest_url', 'tiktok_url', 'threads_url', 'mastodon_url',
            'org_or_person', 'org_name', 'org_alternate_name',
            'org_logo', 'org_description', 'org_email', 'org_phone',
            'org_legal_name', 'org_founding_date', 'org_num_employees',
            'org_vat_id', 'org_tax_id', 'org_iso_6523', 'org_duns',
            'org_lei_code', 'org_naics', 'org_street_address', 'org_address_locality',
            'org_address_region', 'org_postal_code', 'org_address_country',
        ];
        
        foreach ($text_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = sanitize_text_field($settings[$field]);
            }
        }

        $int_fields = [
            'site_logo_id',
            'site_image_id',
            'org_logo_id',
            'person_logo_id',
            'person_user_id',
            'privacy_policy_page',
            'terms_of_service_page',
            'publishing_principles_page',
            'ownership_funding_page',
            'actionable_feedback_page',
            'corrections_policy_page',
            'ethics_policy_page',
            'diversity_policy_page',
            'diversity_staffing_page',
        ];

        foreach ($int_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = absint($settings[$field]);
            }
        }

        if (isset($settings['org_local_business_enabled'])) {
            $sanitized['org_local_business_enabled'] = !empty($settings['org_local_business_enabled']);
        }
        
        // Handle textarea field
        if (isset($settings['custom_meta_tags'])) {
            $sanitized['custom_meta_tags'] = $this->sanitize_site_basics_meta_tags((string) $settings['custom_meta_tags']);
        }
        
        // Handle array fields
        if (isset($settings['additional_profiles']) && is_array($settings['additional_profiles'])) {
            $sanitized['additional_profiles'] = array_map(function($profile) {
                return [
                    'platform' => sanitize_text_field($profile['platform'] ?? ''),
                    'url' => esc_url_raw($profile['url'] ?? '')
                ];
            }, $settings['additional_profiles']);
        }
        
        $existing = get_option('prorank_seo_site_basics', []);
        if (!is_array($existing)) {
            $existing = [];
        }
        $existing = $this->normalize_site_basics_settings($existing);
        $merged = array_merge($existing, $sanitized);

        update_option('prorank_seo_site_basics', $merged);

        // Keep WordPress core site name/tagline in sync.
        if (!empty($merged['site_name'])) {
            update_option('blogname', $merged['site_name']);
        }
        if (!empty($merged['site_tagline'])) {
            update_option('blogdescription', $merged['site_tagline']);
        }

        wp_cache_delete('prorank_site_basics_settings', 'prorank_seo');
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Settings saved successfully', 'prorank-seo'),
            'settings' => $merged,
        ]);
    }

    /**
     * Get default values for Site Basics settings.
     *
     * @return array
     */
    private function get_site_basics_defaults(): array {
        return [
            'site_name' => '',
            'site_alternate_name' => '',
            'site_tagline' => '',
            'title_separator' => '-',
            'site_logo' => '',
            'site_logo_id' => 0,
            'site_image' => '',
            'site_image_id' => 0,
            'google_verification' => '',
            'bing_verification' => '',
            'baidu_verification' => '',
            'yandex_verification' => '',
            'pinterest_verification' => '',
            'norton_verification' => '',
            'custom_meta_tags' => '',
            'facebook_page_url' => '',
            'facebook_authorship' => '',
            'facebook_admin_id' => '',
            'facebook_app_id' => '',
            'facebook_secret' => '',
            'twitter_username' => '',
            'linkedin_url' => '',
            'instagram_url' => '',
            'youtube_url' => '',
            'pinterest_url' => '',
            'tiktok_url' => '',
            'threads_url' => '',
            'mastodon_url' => '',
            'org_or_person' => 'organization',
            'org_name' => '',
            'org_alternate_name' => '',
            'org_logo' => '',
            'org_logo_id' => 0,
            'person_logo' => '',
            'person_logo_id' => 0,
            'person_user_id' => 0,
            'org_description' => '',
            'org_email' => '',
            'org_phone' => '',
            'org_local_business_enabled' => false,
            'org_legal_name' => '',
            'org_founding_date' => '',
            'org_num_employees' => '',
            'org_vat_id' => '',
            'org_tax_id' => '',
            'org_iso_6523' => '',
            'org_duns' => '',
            'org_lei_code' => '',
            'org_naics' => '',
            'org_street_address' => '',
            'org_address_locality' => '',
            'org_address_region' => '',
            'org_postal_code' => '',
            'org_address_country' => '',
            'publishing_principles_page' => 0,
            'ownership_funding_page' => 0,
            'actionable_feedback_page' => 0,
            'corrections_policy_page' => 0,
            'ethics_policy_page' => 0,
            'diversity_policy_page' => 0,
            'diversity_staffing_page' => 0,
            'privacy_policy_page' => 0,
            'terms_of_service_page' => 0,
            'additional_profiles' => [],
        ];
    }

    /**
     * Normalize Site Basics payload keys and legacy aliases.
     *
     * @param array $settings Raw settings array.
     * @return array
     */
    private function normalize_site_basics_settings(array $settings): array {
        if (empty($settings)) {
            return [];
        }

        $aliases = [
            'site_representation' => 'org_or_person',
            'organization_name' => 'org_name',
            'organization_logo' => 'org_logo',
        ];

        $normalized = [];
        foreach ($settings as $key => $value) {
            $target = $aliases[$key] ?? $key;

            if ($target === 'org_or_person') {
                $raw = strtolower((string) $value);
                if (in_array($raw, ['company', 'organization', 'org', 'business'], true)) {
                    $value = 'organization';
                } elseif (in_array($raw, ['person', 'individual'], true)) {
                    $value = 'person';
                } else {
                    $value = 'organization';
                }
            }

            if ($target === 'twitter_username' && is_string($value)) {
                $trimmed = trim($value);
                $trimmed = ltrim($trimmed, '@');

                if (strpos($trimmed, 'twitter.com/') !== false || strpos($trimmed, 'x.com/') !== false) {
                    $parsed = wp_parse_url($trimmed);
                    if (!empty($parsed['path'])) {
                        $path = trim((string) $parsed['path'], '/');
                        $parts = explode('/', $path);
                        $trimmed = $parts[0] ?? '';
                    }
                }

                $value = $trimmed;
            }

            $normalized[$target] = $value;
        }

        return $normalized;
    }

    /**
     * Keep only valid meta tags from the custom verification field.
     *
     * @param string $tags Raw custom meta tags input.
     * @return string
     */
    private function sanitize_site_basics_meta_tags(string $tags): string {
        $tags = trim($tags);
        if ($tags === '') {
            return '';
        }

        preg_match_all('/<meta\b[^>]*>/i', $tags, $matches);
        if (empty($matches[0])) {
            return '';
        }

        $allowed_tags = [
            'meta' => [
                'name' => [],
                'content' => [],
                'property' => [],
                'http-equiv' => [],
                'charset' => [],
            ],
        ];

        $sanitized = [];
        foreach ($matches[0] as $tag) {
            $clean = trim((string) wp_kses($tag, $allowed_tags));
            if ($clean !== '') {
                $sanitized[] = $clean;
            }
        }

        return implode("\n", $sanitized);
    }

    /**
     * Hydrate Site Basics with values imported into legacy options.
     *
     * @param array $settings Canonical Site Basics settings.
     * @return array
     */
    private function hydrate_site_basics_from_legacy_options(array $settings): array {
        $legacy_settings = get_option('prorank_seo_settings', []);
        if (is_array($legacy_settings)) {
            if (
                $this->is_site_basics_value_empty($settings['title_separator'] ?? null) &&
                !empty($legacy_settings['title_separator'])
            ) {
                $settings['title_separator'] = sanitize_text_field((string) $legacy_settings['title_separator']);
            }
        }

        $legacy_social = get_option('prorank_seo_social', []);
        if (is_array($legacy_social)) {
            $social_keys = [
                'facebook_page_url',
                'twitter_username',
                'linkedin_url',
                'instagram_url',
                'youtube_url',
                'pinterest_url',
                'tiktok_url',
                'threads_url',
                'mastodon_url',
            ];

            foreach ($social_keys as $key) {
                if ($this->is_site_basics_value_empty($settings[$key] ?? null) && !empty($legacy_social[$key])) {
                    $settings[$key] = $legacy_social[$key];
                }
            }
        }

        $legacy_schema = get_option('prorank_seo_schema', []);
        if (is_array($legacy_schema)) {
            $mapped_schema = $this->normalize_site_basics_settings($legacy_schema);
            foreach (['org_or_person', 'org_name', 'org_logo'] as $key) {
                if ($this->is_site_basics_value_empty($settings[$key] ?? null) && !empty($mapped_schema[$key])) {
                    $settings[$key] = $mapped_schema[$key];
                }
            }
        }

        if ($this->is_site_basics_value_empty($settings['site_name'] ?? null)) {
            $settings['site_name'] = get_bloginfo('name');
        }
        if ($this->is_site_basics_value_empty($settings['site_tagline'] ?? null)) {
            $settings['site_tagline'] = get_bloginfo('description');
        }

        return $settings;
    }

    /**
     * Determine whether a Site Basics value should be considered empty for fallback purposes.
     *
     * @param mixed $value Value to inspect.
     * @return bool
     */
    private function is_site_basics_value_empty($value): bool {
        if ($value === null) {
            return true;
        }

        if (is_string($value)) {
            return trim($value) === '';
        }

        if (is_array($value)) {
            return empty($value);
        }

        return false;
    }
    
    /**
     * Get breadcrumbs settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_breadcrumbs(WP_REST_Request $request) {
        $defaults = [
            'enabled' => true,
            'separator' => '›',
            'home_text' => 'Home',
            'show_current' => true,
            'show_home' => true,
            'home_icon' => false,
            'auto_insert' => false,
            'position' => 'before',
            'enable_schema' => true,
            'schema_type' => 'jsonld',
            'style' => 'default',
            'display_style' => 'inline',
            'show_on_home' => false,
            'show_on_posts' => true,
            'show_on_pages' => true,
            'show_on_archives' => true,
            'show_on_404' => false,
            'custom_css' => '',
            'enable_cache' => false,
            'aria_label' => __('Breadcrumb', 'prorank-seo'),
            'disable_schema_on' => [],
        ];

        $settings = get_option('prorank_seo_breadcrumbs_settings', null);
        if (!is_array($settings)) {
            $legacy = get_option('prorank_seo_breadcrumbs', []);
            $settings = is_array($legacy) ? $legacy : [];
        }
        $settings = wp_parse_args($settings, $defaults);

        update_option('prorank_seo_breadcrumbs_settings', $settings);
        update_option('prorank_seo_breadcrumbs', $settings);

        return rest_ensure_response([
            'success' => true,
            'data' => $settings,
        ]);
    }
    
    /**
     * Update breadcrumbs settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_breadcrumbs(WP_REST_Request $request) {
        $data = $request->get_param('data');
        
        if (!is_array($data)) {
            $data = $request->get_json_params();
        }
        
        if (!is_array($data)) {
            return $this->get_error_response(
                __('Invalid data format', 'prorank-seo'),
                400
            );
        }
        
        // Sanitize settings
        $sanitized = [];
        
        // Boolean fields
        $bool_fields = [
            'enabled', 'show_current', 'show_home', 'home_icon', 'auto_insert',
            'enable_schema', 'show_on_home', 'show_on_posts',
            'show_on_pages', 'show_on_archives', 'show_on_404', 'enable_cache'
        ];
        
        foreach ($bool_fields as $field) {
            if (isset($data[$field])) {
                $sanitized[$field] = (bool) $data[$field];
            }
        }
        
        // Text fields
        $text_fields = [
            'separator', 'home_text', 'position', 'schema_type',
            'style', 'display_style', 'aria_label'
        ];
        
        foreach ($text_fields as $field) {
            if (isset($data[$field])) {
                $sanitized[$field] = sanitize_text_field($data[$field]);
            }
        }

        if (isset($data['custom_css'])) {
            $sanitized['custom_css'] = sanitize_textarea_field((string) $data['custom_css']);
        }

        if (isset($data['disable_schema_on']) && is_array($data['disable_schema_on'])) {
            $allowed_contexts = ['front_page', 'posts', 'pages', 'archives', '404'];
            $sanitized['disable_schema_on'] = array_values(array_intersect(
                array_map('sanitize_key', $data['disable_schema_on']),
                $allowed_contexts
            ));
        }

        update_option('prorank_seo_breadcrumbs_settings', $sanitized);
        update_option('prorank_seo_breadcrumbs', $sanitized);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Breadcrumbs settings saved successfully', 'prorank-seo'),
        ]);
    }
    
    /**
     * Get titles & meta settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_titles_meta(WP_REST_Request $request) {
        $settings = get_option('prorank_seo_titles_meta', null);
        if (!is_array($settings)) {
            $legacy = get_option('prorank_titles_meta_settings', []);
            $settings = is_array($legacy) ? $legacy : [];
        }

        $normalized = $this->normalize_titles_meta_legacy_keys($settings);
        if (
            $normalized !== $settings
            || !is_array(get_option('prorank_seo_titles_meta', null))
            || !is_array(get_option('prorank_titles_meta_settings', null))
        ) {
            update_option('prorank_seo_titles_meta', $normalized);
            update_option('prorank_titles_meta_settings', $normalized);
            $settings = $normalized;
        }
        
        return rest_ensure_response($settings);
    }
    
    /**
     * Update titles & meta settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_titles_meta(WP_REST_Request $request) {
        $settings = $request->get_json_params();
        
        if (!is_array($settings)) {
            $settings = [];
        }

        $settings = $this->normalize_titles_meta_legacy_keys($settings);
        
        update_option('prorank_seo_titles_meta', $settings);
        update_option('prorank_titles_meta_settings', $settings);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Settings saved successfully', 'prorank-seo'),
        ]);
    }

    /**
     * Normalize legacy titles/meta keys into canonical settings keys.
     *
     * @param array<string,mixed> $settings Raw titles/meta settings.
     * @return array<string,mixed>
     */
    private function normalize_titles_meta_legacy_keys(array $settings): array {
        if (
            (empty($settings['homepage_title']) || !is_string($settings['homepage_title']))
            && isset($settings['home_title'])
            && is_string($settings['home_title'])
            && trim($settings['home_title']) !== ''
        ) {
            $settings['homepage_title'] = $settings['home_title'];
        }

        if (
            (empty($settings['homepage_description']) || !is_string($settings['homepage_description']))
            && isset($settings['home_description'])
            && is_string($settings['home_description'])
            && trim($settings['home_description']) !== ''
        ) {
            $settings['homepage_description'] = $settings['home_description'];
        }

        return $settings;
    }
    
    /**
     * Get content analysis settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_content_analysis(WP_REST_Request $request) {
        $defaults = [
            'enable_realtime' => true,
            'enable_ai_insights' => false,
            'min_content_length' => 300,
            'target_readability_score' => 60,
            'auto_analyze_delay' => 2000,
            'show_keyword_density' => false,
            'show_entity_detection' => false,
            'show_intent_classification' => false,
            // Backward-compatible UI keys used by AI Tools panel.
            'enabled' => true,
            'autoAnalyze' => true,
            'focusKeywordEnabled' => true,
            'seoScoreEnabled' => true,
            'readabilityEnabled' => true,
            'readabilityAlgorithm' => 'flesch-kincaid',
            'targetGradeLevel' => 8,
            'minAcceptableScore' => 60,
            'highlightComplexSentences' => true,
            'maxSentenceLength' => 20,
            'maxParagraphLength' => 150,
        ];

        $stored = get_option('prorank_seo_content_analysis', []);
        if (!is_array($stored)) {
            $stored = [];
        }

        $settings = array_merge($defaults, $stored);

        // Ensure compatibility aliases are always coherent with canonical fields.
        $settings['enabled'] = (bool) $settings['enable_realtime'];
        $settings['autoAnalyze'] = (bool) $settings['enable_realtime'];
        $settings['focusKeywordEnabled'] = (bool) $settings['show_keyword_density'];
        if (!isset($stored['minAcceptableScore'])) {
            $settings['minAcceptableScore'] = (int) $settings['target_readability_score'];
        }

        // Free build: AI insights options are not exposed as functional settings.
        $settings['enable_ai_insights'] = false;
        $settings['show_keyword_density'] = false;
        $settings['show_entity_detection'] = false;
        $settings['show_intent_classification'] = false;
        
        return rest_ensure_response([
            'success' => true,
            'data' => $settings,
            // Some older components read from response.settings.
            'settings' => $settings,
        ]);
    }
    
    /**
     * Update content analysis settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_content_analysis(WP_REST_Request $request) {
        $payload = $request->get_json_params();
        
        if (!is_array($payload)) {
            $payload = $request->get_params();
            if (!is_array($payload)) {
                return $this->get_error_response(
                    __('Invalid settings format', 'prorank-seo'),
                    400
                );
            }
        }

        // Support both flat payload and nested { settings: {...} } payload.
        $settings = $payload;
        if (isset($payload['settings']) && is_array($payload['settings'])) {
            $settings = $payload['settings'];
        }

        // Map compatibility keys from older UI into canonical fields.
        $enabled = array_key_exists('enabled', $settings) ? (bool) $settings['enabled'] : null;
        $auto_analyze = array_key_exists('autoAnalyze', $settings) ? (bool) $settings['autoAnalyze'] : null;
        if ($enabled !== null || $auto_analyze !== null) {
            $settings['enable_realtime'] = ($enabled ?? true) && ($auto_analyze ?? true);
            $settings['enabled'] = ($enabled ?? true);
            $settings['autoAnalyze'] = ($auto_analyze ?? true);
        }

        if (array_key_exists('focusKeywordEnabled', $settings)) {
            $focus_keyword = (bool) $settings['focusKeywordEnabled'];
            $settings['show_keyword_density'] = $focus_keyword;
            $settings['show_entity_detection'] = $focus_keyword;
            $settings['show_intent_classification'] = $focus_keyword;
            $settings['focusKeywordEnabled'] = $focus_keyword;
        }

        if (isset($settings['minAcceptableScore']) && !isset($settings['target_readability_score'])) {
            $settings['target_readability_score'] = (int) $settings['minAcceptableScore'];
        }
        
        // Sanitize settings
        $current = get_option('prorank_seo_content_analysis', []);
        if (!is_array($current)) {
            $current = [];
        }
        $sanitized = $current;
        
        // Boolean fields
        $bool_fields = [
            'enable_realtime',
            'enable_ai_insights',
            'show_keyword_density',
            'show_entity_detection',
            'show_intent_classification',
            // Compatibility/UI flags
            'enabled', 'autoAnalyze', 'focusKeywordEnabled', 'seoScoreEnabled',
            'readabilityEnabled', 'highlightComplexSentences'
        ];
        
        foreach ($bool_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = (bool) $settings[$field];
            }
        }
        
        // Integer fields
        $int_fields = [
            'min_content_length', 'target_readability_score', 'auto_analyze_delay',
            // Compatibility/UI fields
            'targetGradeLevel', 'minAcceptableScore', 'maxSentenceLength', 'maxParagraphLength',
        ];
        foreach ($int_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = absint($settings[$field]);
            }
        }

        if (isset($settings['target_readability_score'])) {
            $sanitized['target_readability_score'] = max(30, min(90, absint($settings['target_readability_score'])));
            // Keep compatibility score in sync.
            $sanitized['minAcceptableScore'] = $sanitized['target_readability_score'];
        } elseif (isset($settings['minAcceptableScore'])) {
            $sanitized['minAcceptableScore'] = max(0, min(100, absint($settings['minAcceptableScore'])));
            $sanitized['target_readability_score'] = max(30, min(90, $sanitized['minAcceptableScore']));
        }

        if (isset($sanitized['min_content_length'])) {
            $sanitized['min_content_length'] = max(100, absint($sanitized['min_content_length']));
        }
        if (isset($sanitized['auto_analyze_delay'])) {
            $sanitized['auto_analyze_delay'] = max(500, min(5000, absint($sanitized['auto_analyze_delay'])));
        }

        // String fields
        if (isset($settings['readabilityAlgorithm'])) {
            $sanitized['readabilityAlgorithm'] = sanitize_text_field((string) $settings['readabilityAlgorithm']);
        }

        $sanitized['enabled'] = (bool) ($sanitized['enable_realtime'] ?? true);
        $sanitized['autoAnalyze'] = (bool) ($sanitized['enable_realtime'] ?? true);
        $sanitized['focusKeywordEnabled'] = (bool) ($sanitized['show_keyword_density'] ?? false);

        // Free build: lock Pro+ AI analysis switches.
        $sanitized['enable_ai_insights'] = false;
        $sanitized['show_keyword_density'] = false;
        $sanitized['show_entity_detection'] = false;
        $sanitized['show_intent_classification'] = false;
        $sanitized['focusKeywordEnabled'] = false;
        
        update_option('prorank_seo_content_analysis', $sanitized);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Settings saved successfully', 'prorank-seo'),
            'data' => $sanitized,
            'settings' => $sanitized,
        ]);
    }
    
    /**
     * Get podcast settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_podcast_settings(WP_REST_Request $request) {
        $defaults = [
            'podcast_title' => '',
            'podcast_subtitle' => '',
            'podcast_author' => '',
            'podcast_email' => '',
            'podcast_category' => '',
            'podcast_subcategory' => '',
            'podcast_explicit' => 'no',
            'podcast_language' => '',
            'podcast_copyright' => '',
            'podcast_image' => '',
            'podcast_owner_name' => '',
            'podcast_owner_email' => '',
            'enable_podcast_feed' => false,
            'podcast_feed_limit' => '',
            'enable_itunes_tags' => true,
            'enable_spotify_tags' => false,
            'enable_youtube_tags' => false,
            'podcast_redirect_feed' => '',
            'enable_transcripts' => false,
            'enable_chapters' => false,
            'enable_value4value' => false,
            'enable_video_podcasts' => false,
            'lightning_address' => '',
            'funding_url' => '',
        ];
        
        $settings = get_option('prorank_seo_podcast', $defaults);
        $settings = wp_parse_args($settings, $defaults);
        
        return rest_ensure_response([
            'success' => true,
            'data' => $settings,
        ]);
    }
    
    /**
     * Update podcast settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_podcast_settings(WP_REST_Request $request) {
        $settings = $request->get_param('settings');
        
        if (!is_array($settings)) {
            return new \WP_Error(
                'invalid_settings',
                __('Invalid settings data', 'prorank-seo'),
                ['status' => 400]
            );
        }
        
        $sanitized = [];
        
        // Boolean fields
        $bool_fields = [
            'enable_podcast_feed', 'enable_itunes_tags', 'enable_spotify_tags',
            'enable_youtube_tags', 'enable_transcripts', 'enable_chapters',
            'enable_value4value', 'enable_video_podcasts'
        ];
        
        foreach ($bool_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = (bool) $settings[$field];
            }
        }
        
        // Text fields
        $text_fields = [
            'podcast_title', 'podcast_author', 'podcast_category',
            'podcast_subcategory', 'podcast_explicit', 'podcast_language',
            'podcast_copyright', 'podcast_owner_name'
        ];
        
        foreach ($text_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = sanitize_text_field($settings[$field]);
            }
        }
        
        // Textarea field
        if (isset($settings['podcast_subtitle'])) {
            $sanitized['podcast_subtitle'] = sanitize_textarea_field($settings['podcast_subtitle']);
        }
        
        // Email fields
        $email_fields = ['podcast_email', 'podcast_owner_email'];
        foreach ($email_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = sanitize_email($settings[$field]);
            }
        }
        
        // URL fields
        $url_fields = ['podcast_image', 'podcast_redirect_feed', 'funding_url'];
        foreach ($url_fields as $field) {
            if (isset($settings[$field])) {
                $sanitized[$field] = esc_url_raw($settings[$field]);
            }
        }
        
        // Special fields
        if (isset($settings['podcast_feed_limit'])) {
            $sanitized['podcast_feed_limit'] = absint($settings['podcast_feed_limit']);
        }
        
        if (isset($settings['lightning_address'])) {
            $sanitized['lightning_address'] = sanitize_text_field($settings['lightning_address']);
        }
        
        update_option('prorank_seo_podcast', $sanitized);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Podcast settings saved successfully', 'prorank-seo'),
            'data' => $sanitized,
        ]);
    }
    
    /**
     * Get all schemas
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_schemas(WP_REST_Request $request) {
        $schemas = get_option('prorank_seo_schemas', []);
        
        return rest_ensure_response([
            'schemas' => $schemas,
        ]);
    }
    
    /**
     * Get single schema
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_schema(WP_REST_Request $request) {
        $id = $request->get_param('id');
        $schemas = get_option('prorank_seo_schemas', []);
        
        $schema = null;
        foreach ($schemas as $s) {
            if ($s['id'] == $id) {
                $schema = $s;
                break;
            }
        }
        
        if (!$schema) {
            return new \WP_Error(
                'schema_not_found',
                __('Schema not found', 'prorank-seo'),
                ['status' => 404]
            );
        }
        
        return rest_ensure_response($schema);
    }
    
    /**
     * Create new schema
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function create_schema(WP_REST_Request $request) {
        $data = $request->get_json_params();
        
        if (empty($data['type']) || empty($data['name'])) {
            return new \WP_Error(
                'invalid_schema',
                __('Schema type and name are required', 'prorank-seo'),
                ['status' => 400]
            );
        }
        
        $schemas = get_option('prorank_seo_schemas', []);
        
        // Generate unique ID
        $id = time() . '_' . wp_rand(1000, 9999);
        
        $new_schema = [
            'id' => $id,
            'name' => sanitize_text_field($data['name']),
            'type' => sanitize_text_field($data['type']),
            'targeting' => $data['targeting'] ?? [],
            'mapping' => $data['mapping'] ?? [],
            'status' => $data['status'] ?? 'active',
            'priority' => intval($data['priority'] ?? 10),
            'created' => current_time('mysql'),
            'modified' => current_time('mysql'),
        ];
        
        $schemas[] = $new_schema;
        update_option('prorank_seo_schemas', $schemas);
        
        return rest_ensure_response([
            'success' => true,
            'schema' => $new_schema,
        ]);
    }
    
    /**
     * Update existing schema
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_schema(WP_REST_Request $request) {
        $id = $request->get_param('id');
        $data = $request->get_json_params();
        
        $schemas = get_option('prorank_seo_schemas', []);
        
        $found = false;
        foreach ($schemas as &$schema) {
            if ($schema['id'] == $id) {
                $schema['name'] = sanitize_text_field($data['name'] ?? $schema['name']);
                $schema['type'] = sanitize_text_field($data['type'] ?? $schema['type']);
                $schema['targeting'] = $data['targeting'] ?? $schema['targeting'];
                $schema['mapping'] = $data['mapping'] ?? $schema['mapping'];
                $schema['status'] = $data['status'] ?? $schema['status'];
                $schema['priority'] = intval($data['priority'] ?? $schema['priority']);
                $schema['modified'] = current_time('mysql');
                $found = true;
                break;
            }
        }
        
        if (!$found) {
            return new \WP_Error(
                'schema_not_found',
                __('Schema not found', 'prorank-seo'),
                ['status' => 404]
            );
        }
        
        update_option('prorank_seo_schemas', $schemas);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Schema updated successfully', 'prorank-seo'),
        ]);
    }
    
    /**
     * Delete schema
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function delete_schema(WP_REST_Request $request) {
        $id = $request->get_param('id');
        
        $schemas = get_option('prorank_seo_schemas', []);
        $filtered = [];
        $found = false;
        
        foreach ($schemas as $schema) {
            if ($schema['id'] != $id) {
                $filtered[] = $schema;
            } else {
                $found = true;
            }
        }
        
        if (!$found) {
            return new \WP_Error(
                'schema_not_found',
                __('Schema not found', 'prorank-seo'),
                ['status' => 404]
            );
        }
        
        update_option('prorank_seo_schemas', $filtered);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Schema deleted successfully', 'prorank-seo'),
        ]);
    }
    
    /**
     * Toggle schema status
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function toggle_schema_status(WP_REST_Request $request) {
        $id = $request->get_param('id');
        $data = $request->get_json_params();
        $new_status = $data['status'] ?? null;
        
        if (!in_array($new_status, ['active', 'inactive'])) {
            return new \WP_Error(
                'invalid_status',
                __('Invalid status value', 'prorank-seo'),
                ['status' => 400]
            );
        }
        
        $schemas = get_option('prorank_seo_schemas', []);
        
        $found = false;
        foreach ($schemas as &$schema) {
            if ($schema['id'] == $id) {
                $schema['status'] = $new_status;
                $schema['modified'] = current_time('mysql');
                $found = true;
                break;
            }
        }
        
        if (!$found) {
            return new \WP_Error(
                'schema_not_found',
                __('Schema not found', 'prorank-seo'),
                ['status' => 404]
            );
        }
        
        update_option('prorank_seo_schemas', $schemas);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Schema status updated', 'prorank-seo'),
        ]);
    }
    
    /**
     * Get custom fields
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_custom_fields(WP_REST_Request $request) {
        global $wpdb;
        
        // Get ACF fields if available
        $acf_fields = [];
        if (function_exists('acf_get_field_groups')) {
            $field_groups = acf_get_field_groups();
            foreach ($field_groups as $group) {
                $fields = acf_get_fields($group['key']);
                foreach ($fields as $field) {
                    $acf_fields[] = [
                        'label' => $field['label'],
                        'value' => 'acf_' . $field['name'],
                        'type' => $field['type'],
                    ];
                }
            }
        }
        
        // Get post meta keys
        $meta_keys = $wpdb->get_col("
            SELECT DISTINCT meta_key 
            FROM {$wpdb->postmeta} 
            WHERE meta_key NOT LIKE '\_%' 
            LIMIT 100
        ");
        
        $custom_fields = [];
        foreach ($meta_keys as $key) {
            $custom_fields[] = [
                'label' => ucwords(str_replace('_', ' ', $key)),
                'value' => 'meta_' . $key,
                'type' => 'text',
            ];
        }
        
        // Merge ACF and custom fields
        $all_fields = array_merge($acf_fields, $custom_fields);
        
        return rest_ensure_response($all_fields);
    }
}
