"""Custom validators for ToothFairy models."""

import re
from typing import Any, Dict, List, Optional

from pydantic import field_validator


def validate_temperature(value: Optional[float]) -> Optional[float]:
    """Validate temperature is in valid range [0.001, 1.0].
    
    Args:
        value: Temperature value to validate
        
    Returns:
        Validated temperature
        
    Raises:
        ValueError: If temperature out of range
    """
    if value is None:
        return value
    if not 0.001 <= value <= 1.0:
        raise ValueError(
            f"temperature must be between 0.001 and 1.0, got {value}"
        )
    return value


def validate_max_tokens(value: Optional[int]) -> Optional[int]:
    """Validate max_tokens is positive.
    
    Args:
        value: Max tokens value to validate
        
    Returns:
        Validated max_tokens
        
    Raises:
        ValueError: If max_tokens is not positive
    """
    if value is None:
        return value
    if value <= 0:
        raise ValueError(f"max_tokens must be positive, got {value}")
    return value


def validate_top_k(value: Optional[int]) -> Optional[int]:
    """Validate top_k is in valid range [1, 50].
    
    Args:
        value: Top K value to validate
        
    Returns:
        Validated top_k
        
    Raises:
        ValueError: If top_k out of range
    """
    if value is None:
        return value
    if not 1 <= value <= 50:
        raise ValueError(f"top_k must be between 1 and 50, got {value}")
    return value


def validate_json_schema(value: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
    """Validate function parameters use JSON Schema format.
    
    The API expects: {"type": "object", "properties": {...}, "required": [...]}
    NOT the deprecated format: [{"name": "...", "type": "..."}]
    
    Args:
        value: Parameters dictionary to validate
        
    Returns:
        Validated parameters
        
    Raises:
        ValueError: If using deprecated list format or missing required keys
    """
    if value is None:
        return value
    
    if isinstance(value, list):
        raise ValueError(
            "parameters must use JSON Schema format: "
            '{"type": "object", "properties": {...}, "required": [...]}. '
            f"Got deprecated list format: {value}"
        )
    
    if isinstance(value, dict):
        if value.get("type") != "object":
            raise ValueError(
                f'parameters must have type="object", got type="{value.get("type")}"'
            )
        if "properties" not in value:
            raise ValueError(
                "parameters must include 'properties' key with parameter definitions"
            )
    
    return value


def validate_cron_expression(value: Optional[str]) -> Optional[str]:
    """Validate cron expression format.
    
    Supports standard 5-field cron: minute hour day month weekday
    
    Args:
        value: Cron expression to validate
        
    Returns:
        Validated cron expression
        
    Raises:
        ValueError: If cron expression is invalid
    """
    if value is None:
        return value
    
    parts = value.strip().split()
    if len(parts) != 5:
        raise ValueError(
            f"cron expression must have 5 fields (minute hour day month weekday), "
            f"got {len(parts)} fields: '{value}'"
        )
    
    return value


def validate_interpolation_string(value: Optional[str]) -> Optional[str]:
    """Validate interpolation_string minimum length.
    
    Prompts require at least 128 characters for meaningful content.
    
    Args:
        value: Interpolation string to validate
        
    Returns:
        Validated interpolation string
        
    Raises:
        ValueError: If string too short
    """
    if value is None:
        return value
    if len(value) < 128:
        raise ValueError(
            f"interpolation_string must be at least 128 characters, "
            f"got {len(value)} characters"
        )
    return value


def validate_url(value: Optional[str]) -> Optional[str]:
    """Validate URL format.
    
    Args:
        value: URL to validate
        
    Returns:
        Validated URL
        
    Raises:
        ValueError: If URL format is invalid
    """
    if value is None:
        return value
    
    url_pattern = re.compile(
        r'^https?://'
        r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|'
        r'localhost|'
        r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
        r'(?::\d+)?'
        r'(?:/?|[/?]\S+)$',
        re.IGNORECASE
    )
    
    if not url_pattern.match(value):
        raise ValueError(f"invalid URL format: {value}")
    
    return value


def validate_hex_color(value: Optional[str]) -> Optional[str]:
    """Validate hex color format.
    
    Args:
        value: Color string to validate
        
    Returns:
        Validated color
        
    Raises:
        ValueError: If not valid hex color
    """
    if value is None:
        return value
    
    if not re.match(r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$', value):
        raise ValueError(f"invalid hex color format: {value}")
    
    return value