<?php
/**
 * Module Settings REST API Controller
 * 
 * Handles module-specific settings storage and retrieval
 * 
 * @package WooNooW\Api
 */

namespace WooNooW\Api;

use WP_REST_Controller;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use WooNooW\Core\ModuleRegistry;

class ModuleSettingsController extends WP_REST_Controller {
    
    /**
     * REST API namespace
     */
    protected $namespace = 'woonoow/v1';
    
    /**
     * REST API base
     */
    protected $rest_base = 'modules';
    
    /**
     * Register routes
     */
    public function register_routes() {
        // GET /woonoow/v1/modules/{module_id}/settings (public - needed by frontend)
        register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<module_id>[a-zA-Z0-9_-]+)/settings', [
            [
                'methods' => WP_REST_Server::READABLE,
                'callback' => [$this, 'get_settings'],
                'permission_callback' => '__return_true', // Public: settings are non-sensitive, needed by customer pages
                'args' => [
                    'module_id' => [
                        'required' => true,
                        'type' => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                ],
            ],
        ]);
        
        // POST /woonoow/v1/modules/{module_id}/settings
        register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<module_id>[a-zA-Z0-9_-]+)/settings', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'update_settings'],
                'permission_callback' => [$this, 'check_permission'],
                'args' => [
                    'module_id' => [
                        'required' => true,
                        'type' => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                ],
            ],
        ]);
        
        // GET /woonoow/v1/modules/{module_id}/schema
        register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<module_id>[a-zA-Z0-9_-]+)/schema', [
            [
                'methods' => WP_REST_Server::READABLE,
                'callback' => [$this, 'get_schema'],
                'permission_callback' => [$this, 'check_permission'],
                'args' => [
                    'module_id' => [
                        'required' => true,
                        'type' => 'string',
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                ],
            ],
        ]);
    }
    
    /**
     * Check permission
     * 
     * @return bool
     */
    public function check_permission() {
        return current_user_can('manage_options');
    }
    
    /**
     * Get module settings
     * 
     * @param WP_REST_Request $request
     * @return WP_REST_Response|WP_Error
     */
    public function get_settings($request) {
        $module_id = $request['module_id'];
        
        // Verify module exists
        $modules = ModuleRegistry::get_all_modules();
        if (!isset($modules[$module_id])) {
            return new WP_Error(
                'invalid_module',
                __('Invalid module ID', 'woonoow'),
                ['status' => 404]
            );
        }
        
        // Get settings from database
        $settings = get_option("woonoow_module_{$module_id}_settings", []);
        
        // Apply defaults from schema if available
        $schema = apply_filters('woonoow/module_settings_schema', []);
        if (isset($schema[$module_id])) {
            $defaults = $this->get_schema_defaults($schema[$module_id]);
            $settings = wp_parse_args($settings, $defaults);
        }
        
        return new WP_REST_Response($settings, 200);
    }
    
    /**
     * Update module settings
     * 
     * @param WP_REST_Request $request
     * @return WP_REST_Response|WP_Error
     */
    public function update_settings($request) {
        $module_id = $request['module_id'];
        $new_settings = $request->get_json_params();
        
        // Verify module exists
        $modules = ModuleRegistry::get_all_modules();
        if (!isset($modules[$module_id])) {
            return new WP_Error(
                'invalid_module',
                __('Invalid module ID', 'woonoow'),
                ['status' => 404]
            );
        }
        
        // Validate against schema if available
        $schema = apply_filters('woonoow/module_settings_schema', []);
        if (isset($schema[$module_id])) {
            $validated = $this->validate_settings($new_settings, $schema[$module_id]);
            if (is_wp_error($validated)) {
                return $validated;
            }
            $new_settings = $validated;
        }
        
        // Save settings
        update_option("woonoow_module_{$module_id}_settings", $new_settings);
        
        // Allow addons to react to settings changes
        do_action("woonoow/module_settings_updated/{$module_id}", $new_settings);
        do_action('woonoow/module_settings_updated', $module_id, $new_settings);
        
        return rest_ensure_response([
            'success' => true,
            'message' => __('Settings saved successfully', 'woonoow'),
            'settings' => $new_settings,
        ], 200);
    }
    
    /**
     * Get settings schema for a module
     * 
     * @param WP_REST_Request $request
     * @return WP_REST_Response|WP_Error
     */
    public function get_schema($request) {
        $module_id = $request['module_id'];
        
        // Verify module exists
        $modules = ModuleRegistry::get_all_modules();
        if (!isset($modules[$module_id])) {
            return new WP_Error(
                'invalid_module',
                __('Invalid module ID', 'woonoow'),
                ['status' => 404]
            );
        }
        
        // Get schema from filter
        $all_schemas = apply_filters('woonoow/module_settings_schema', []);
        $schema = $all_schemas[$module_id] ?? null;
        
        if (!$schema) {
            return new WP_REST_Response([
                'schema' => null,
                'message' => __('No schema available for this module', 'woonoow'),
            ], 200);
        }
        
        return new WP_REST_Response([
            'schema' => $schema,
        ], 200);
    }
    
    /**
     * Get default values from schema
     * 
     * @param array $schema
     * @return array
     */
    private function get_schema_defaults($schema) {
        $defaults = [];
        
        foreach ($schema as $key => $field) {
            if (isset($field['default'])) {
                $defaults[$key] = $field['default'];
            }
        }
        
        return $defaults;
    }
    
    /**
     * Validate settings against schema
     * 
     * @param array $settings
     * @param array $schema
     * @return array|WP_Error
     */
    private function validate_settings($settings, $schema) {
        $validated = [];
        $errors = [];
        
        foreach ($schema as $key => $field) {
            $value = $settings[$key] ?? null;
            
            // Check required fields
            if (!empty($field['required']) && ($value === null || $value === '')) {
                $errors[$key] = sprintf(
                    __('%s is required', 'woonoow'),
                    $field['label'] ?? $key
                );
                continue;
            }
            
            // Skip validation if value is null and not required
            if ($value === null) {
                continue;
            }
            
            // Type validation
            $type = $field['type'] ?? 'text';
            $min = isset($field['min']) ? $field['min'] : null;
            $max = isset($field['max']) ? $field['max'] : null;

            switch ($type) {
                case 'text':
                case 'textarea':
                case 'email':
                case 'url':
                    $validated[$key] = sanitize_text_field($value);
                    break;

                case 'number':
                    // Handle empty string as valid for numbers (if min allows 0)
                    if ($value === '' || $value === null) {
                        // Only allow empty if there's a default
                        if (isset($field['default'])) {
                            $validated[$key] = $field['default'];
                        } elseif ($min !== null && $min === 0) {
                            $validated[$key] = 0;
                        } else {
                            $errors[$key] = sprintf(
                                __('%s cannot be empty', 'woonoow'),
                                $field['label'] ?? $key
                            );
                        }
                    } else {
                        $num_value = floatval($value);
                        if ($min !== null && $num_value < $min) {
                            $errors[$key] = sprintf(
                                __('%s must be at least %s', 'woonoow'),
                                $field['label'] ?? $key,
                                $min
                            );
                        } elseif ($max !== null && $num_value > $max) {
                            $errors[$key] = sprintf(
                                __('%s must be at most %s', 'woonoow'),
                                $field['label'] ?? $key,
                                $max
                            );
                        } else {
                            $validated[$key] = $num_value;
                        }
                    }
                    break;
                    
                case 'toggle':
                case 'checkbox':
                    $validated[$key] = (bool) $value;
                    break;
                    
                case 'select':
                    // Validate against allowed options
                    if (isset($field['options']) && !isset($field['options'][$value])) {
                        $errors[$key] = sprintf(
                            __('Invalid value for %s', 'woonoow'),
                            $field['label'] ?? $key
                        );
                    } else {
                        $validated[$key] = sanitize_text_field($value);
                    }
                    break;

                case 'multiselect':
                    // Validate array of values against allowed options
                    if (!is_array($value)) {
                        $value = [];
                    }
                    $allowed_options = $field['options'] ?? [];
                    $valid_values = [];
                    foreach ($value as $v) {
                        if (isset($allowed_options[$v])) {
                            $valid_values[] = sanitize_text_field($v);
                        }
                    }
                    $validated[$key] = $valid_values;
                    break;
                    
                default:
                    $validated[$key] = $value;
            }
        }
        
        if (!empty($errors)) {
            return new WP_Error(
                'validation_failed',
                __('Settings validation failed', 'woonoow'),
                ['status' => 400, 'errors' => $errors]
            );
        }
        
        return $validated;
    }
}
