<?php
/**
 * Validator Helper
 *
 * @package ZenoChatbot\Helper
 */

namespace ZenoChatbot\Helper;

use ZenoChatbot\App;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Validation utilities for data validation
 */
class Validator
{
    /**
     * Validate email address
     *
     * @param string $email
     * @return bool
     */
    public static function isValidEmail($email)
    {
        return is_email($email);
    }

    /**
     * Validate URL
     *
     * @param string $url
     * @return bool
     */
    public static function isValidUrl($url)
    {
        return filter_var($url, FILTER_VALIDATE_URL) !== false;
    }

    /**
     * Validate API key format for different providers
     *
     * @param string $apiKey
     * @param string $provider
     * @return bool
     */
    public static function isValidApiKeyFormat($apiKey, $provider = null)
    {
        if (empty($apiKey)) {
            return false;
        }

        // If provider is specified, use provider-specific validation
        if ($provider) {
            return self::validateProviderApiKey($apiKey, $provider);
        }

        // Generic API key validation (at least 10 characters, alphanumeric with some special chars)
        return preg_match('/^[a-zA-Z0-9\-_\.]{10,}$/', $apiKey);
    }

    /**
     * Validate provider-specific API key format
     *
     * @param string $apiKey
     * @param string $provider
     * @return bool
     */
    private static function validateProviderApiKey($apiKey, $provider)
    {
        $config = App::config("llm.providers.{$provider}");

        if (!$config || !isset($config['api_key_format'])) {
            return self::isValidApiKeyFormat($apiKey);
        }

        $pattern = '/' . $config['api_key_format'] . '/';
        return preg_match($pattern, $apiKey);
    }

    /**
     * Validate temperature value
     *
     * @param float $temperature
     * @return bool
     */
    public static function isValidTemperature($temperature)
    {
        $limits = App::config('llm.limits.temperature', ['min' => 0.0, 'max' => 2.0]);
        return is_numeric($temperature) &&
               $temperature >= $limits['min'] &&
               $temperature <= $limits['max'];
    }

    /**
     * Validate max tokens value
     *
     * @param int $maxTokens
     * @return bool
     */
    public static function isValidMaxTokens($maxTokens)
    {
        $limits = App::config('llm.limits.max_tokens', ['min' => 50, 'max' => 8192]);
        return is_numeric($maxTokens) &&
               $maxTokens >= $limits['min'] &&
               $maxTokens <= $limits['max'];
    }

    /**
     * Validate LLM provider name (must be enabled)
     *
     * @param string $provider
     * @return bool
     */
    public static function isValidProvider($provider)
    {
        $providers = App::config('api.llm_providers', []);

        // Check if provider exists
        if (!isset($providers[$provider])) {
            return false;
        }

        // Check if provider is enabled
        $providerConfig = $providers[$provider];
        if (isset($providerConfig['enabled']) && $providerConfig['enabled'] === false) {
            return false;
        }

        return true;
    }

    /**
     * Validate model name for a specific provider
     *
     * @param string $model
     * @param string $provider
     * @return bool
     */
    public static function isValidModel($model, $provider)
    {
        $config = App::config("llm.providers.{$provider}.models");
        return $config && isset($config[$model]);
    }

    /**
     * Validate system prompt length
     *
     * @param string $prompt
     * @return bool
     */
    public static function isValidSystemPrompt($prompt)
    {
        $maxLength = App::config('llm.limits.system_prompt.max_length', 2000);
        return strlen($prompt) <= $maxLength;
    }

    /**
     * Validate post types array
     *
     * @param array $postTypes
     * @return bool
     */
    public static function isValidPostTypes($postTypes)
    {
        if (!is_array($postTypes)) {
            return false;
        }

        $availablePostTypes = get_post_types(['public' => true], 'names');

        foreach ($postTypes as $postType) {
            if (!in_array($postType, $availablePostTypes)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Validate widget position
     *
     * @param string $position
     * @return bool
     */
    public static function isValidWidgetPosition($position)
    {
        $validPositions = ['bottom-right', 'bottom-left', 'top-right', 'top-left'];
        return in_array($position, $validPositions);
    }

    /**
     * Validate integer within range
     *
     * @param mixed $value
     * @param int $min
     * @param int $max
     * @return bool
     */
    public static function isValidIntRange($value, $min, $max)
    {
        return is_numeric($value) &&
               intval($value) >= $min &&
               intval($value) <= $max;
    }

    /**
     * Validate float within range
     *
     * @param mixed $value
     * @param float $min
     * @param float $max
     * @return bool
     */
    public static function isValidFloatRange($value, $min, $max)
    {
        return is_numeric($value) &&
               floatval($value) >= $min &&
               floatval($value) <= $max;
    }

    /**
     * Validate required fields in array
     *
     * @param array $data
     * @param array $requiredFields
     * @return array Array with 'valid' boolean and 'missing' array
     */
    public static function validateRequiredFields($data, $requiredFields)
    {
        $missing = [];

        foreach ($requiredFields as $field) {
            if (!isset($data[$field]) || empty($data[$field])) {
                $missing[] = $field;
            }
        }

        return [
            'valid' => empty($missing),
            'missing' => $missing
        ];
    }

    /**
     * Validate JSON string
     *
     * @param string $json
     * @return bool
     */
    public static function isValidJson($json)
    {
        json_decode($json);
        return json_last_error() === JSON_ERROR_NONE;
    }

    /**
     * Validate hex color code
     *
     * @param string $color
     * @return bool
     */
    public static function isValidHexColor($color)
    {
        return preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $color);
    }

    /**
     * Validate WordPress capability
     *
     * @param string $capability
     * @return bool
     */
    public static function isValidCapability($capability)
    {
        $validCapabilities = [
            'manage_options',
            'edit_posts',
            'edit_pages',
            'edit_others_posts',
            'publish_posts',
            'read'
        ];

        return in_array($capability, $validCapabilities);
    }

    /**
     * Comprehensive validation for LLM settings
     *
     * @param array $settings
     * @return array
     */
    public static function validateLLMSettings($settings)
    {
        $errors = [];

        // Validate provider
        if (isset($settings['provider']) && !self::isValidProvider($settings['provider'])) {
            $errors['provider'] = 'Invalid LLM provider';
        }

        // Validate temperature
        if (isset($settings['temperature']) && !self::isValidTemperature($settings['temperature'])) {
            $errors['temperature'] = 'Temperature must be between 0 and 2';
        }

        // Validate max tokens
        if (isset($settings['max_tokens']) && !self::isValidMaxTokens($settings['max_tokens'])) {
            $errors['max_tokens'] = 'Max tokens must be between 50 and 8192';
        }

        // Validate system prompt
        if (isset($settings['system_prompt']) && !self::isValidSystemPrompt($settings['system_prompt'])) {
            $errors['system_prompt'] = 'System prompt is too long (max 2000 characters)';
        }

        // Validate provider-specific settings
        if (isset($settings['providers']) && is_array($settings['providers'])) {
            foreach ($settings['providers'] as $provider => $config) {
                if (!self::isValidProvider($provider)) {
                    continue;
                }

                if (isset($config['api_key']) && !empty($config['api_key'])) {
                    if (!self::isValidApiKeyFormat($config['api_key'], $provider)) {
                        $errors["providers.{$provider}.api_key"] = "Invalid API key format for {$provider}";
                    }
                }

                if (isset($config['model']) && !self::isValidModel($config['model'], $provider)) {
                    $errors["providers.{$provider}.model"] = "Invalid model for {$provider}";
                }
            }
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors
        ];
    }
}
