"""
Validation utilities for configuration validation.

This module provides validation functions for agent, pattern, and tool
configurations, ensuring correctness before instantiation.
"""

from typing import Any, Dict, List
from pydantic import BaseModel, ValidationError


class ValidationResult(BaseModel):
    """
    Result of configuration validation.

    :param valid: bool - Whether validation passed.
    :param errors: List[str] - Validation errors (blocking).
    :param warnings: List[str] - Validation warnings (non-blocking).
    """

    valid: bool
    errors: List[str] = []
    warnings: List[str] = []


def validate_agent_config(config: Dict[str, Any]) -> ValidationResult:
    """
    Validate agent configuration dictionary.

    Checks for required fields and validates parameter ranges for
    agent configuration before creating an AgentConfig instance.

    :param config: Dict[str, Any] - Agent configuration to validate.
    :return: ValidationResult - Validation outcome with errors/warnings.
    """
    errors = []
    warnings = []

    required_fields = ["name", "model"]
    for field in required_fields:
        if field not in config:
            errors.append(f"Missing required field: {field}")

    if "temperature" in config:
        temp = config["temperature"]
        if not isinstance(temp, (int, float)) or temp < 0 or temp > 2:
            errors.append("Temperature must be between 0 and 2")

    if "max_tokens" in config:
        tokens = config["max_tokens"]
        if not isinstance(tokens, int) or tokens < 1:
            errors.append("Max tokens must be a positive integer")

    return ValidationResult(valid=len(errors) == 0, errors=errors, warnings=warnings)


def validate_pattern_config(config: Dict[str, Any]) -> ValidationResult:
    """
    Validate pattern configuration dictionary.

    Checks for required fields and validates parameter ranges for
    pattern configuration before creating a PatternConfig instance.

    :param config: Dict[str, Any] - Pattern configuration to validate.
    :return: ValidationResult - Validation outcome with errors/warnings.
    """
    errors = []
    warnings = []

    required_fields = ["name", "pattern_type"]
    for field in required_fields:
        if field not in config:
            errors.append(f"Missing required field: {field}")

    if "max_iterations" in config:
        iterations = config["max_iterations"]
        if not isinstance(iterations, int) or iterations < 1:
            errors.append("Max iterations must be a positive integer")
        elif iterations > 100:
            warnings.append("Max iterations > 100 may cause performance issues")

    if "timeout" in config:
        timeout = config["timeout"]
        if timeout is not None and (not isinstance(timeout, (int, float)) or timeout <= 0):
            errors.append("Timeout must be a positive number")

    valid_pattern_types = ["reflection", "tool_use", "react", "planning", "multi_agent"]
    if "pattern_type" in config and config["pattern_type"] not in valid_pattern_types:
        errors.append(f"Invalid pattern_type. Must be one of: {', '.join(valid_pattern_types)}")

    return ValidationResult(valid=len(errors) == 0, errors=errors, warnings=warnings)


def validate_tool_config(config: Dict[str, Any]) -> ValidationResult:
    """
    Validate tool configuration dictionary.

    Checks for required fields and validates parameter ranges for
    tool configuration before creating a ToolConfig instance.

    :param config: Dict[str, Any] - Tool configuration to validate.
    :return: ValidationResult - Validation outcome with errors/warnings.
    """
    errors = []
    warnings = []

    required_fields = ["name", "description"]
    for field in required_fields:
        if field not in config:
            errors.append(f"Missing required field: {field}")

    if "timeout" in config:
        timeout = config["timeout"]
        if timeout is not None and (not isinstance(timeout, (int, float)) or timeout <= 0):
            errors.append("Timeout must be a positive number")

    valid_categories = ["search", "computation", "data_access", "communication", "custom"]
    if "category" in config and config["category"] not in valid_categories:
        errors.append(f"Invalid category. Must be one of: {', '.join(valid_categories)}")

    return ValidationResult(valid=len(errors) == 0, errors=errors, warnings=warnings)


def validate_pydantic_model(model_class: type[BaseModel], data: Dict[str, Any]) -> ValidationResult:
    """
    Validate data against a Pydantic model.

    Attempts to instantiate the model with the provided data and
    captures any validation errors.

    :param model_class: type[BaseModel] - Pydantic model class to validate against.
    :param data: Dict[str, Any] - Data to validate.
    :return: ValidationResult - Validation outcome with errors.
    """
    try:
        model_class(**data)
        return ValidationResult(valid=True)
    except ValidationError as e:
        errors = [f"{err['loc'][0]}: {err['msg']}" for err in e.errors()]
        return ValidationResult(valid=False, errors=errors)
