"""
Configuration management for InferenceKit.
Handles configuration loading, validation, and management.
"""

import os
import json
import yaml
import toml
import threading
from pathlib import Path
from typing import Dict, Any, Optional, Union, List, Callable, Tuple
from pydantic import BaseModel, Field, validator, root_validator
from dataclasses import dataclass, field, asdict
from enum import Enum
from datetime import datetime
import copy
import time
from collections import defaultdict
import logging
from functools import partial

from .types import (
    ProviderType,
    ModelType,
    ProviderConfig,
    ModelConfig,
    CacheConfig,
    Request,
    Response,
    CacheEntry,
)


class LogLevel(str, Enum):
    """Log levels for configuration."""
    DEBUG = "DEBUG"
    INFO = "INFO"
    WARNING = "WARNING"
    ERROR = "ERROR"
    CRITICAL = "CRITICAL"


class Environment(str, Enum):
    """Supported environments."""
    DEVELOPMENT = "development"
    PRODUCTION = "production"
    TESTING = "testing"
    STAGING = "staging"


class ProviderConfigSchema(BaseModel):
    """Enhanced provider configuration schema."""
    api_key: str
    base_url: Optional[str] = Field(None, description="Base URL for the provider API")
    timeout: float = Field(10.0, ge=0.1, description="Request timeout in seconds")
    max_retries: int = Field(3, ge=0, description="Maximum number of retry attempts")
    retry_delay: float = Field(1.0, ge=0.1, description="Delay between retries in seconds")
    headers: Dict[str, str] = Field(default_factory=dict, description="Additional headers")
    verify_ssl: bool = Field(True, description="Verify SSL certificates")
    proxy: Optional[str] = Field(None, description="Proxy URL")


class CacheConfigSchema(BaseModel):
    """Enhanced cache configuration schema."""
    enabled: bool = Field(True, description="Enable caching")
    max_size: int = Field(1000, ge=1, description="Maximum number of cached items")
    similarity_threshold: float = Field(0.8, ge=0.0, le=1.0, description="Similarity threshold for cache hits")
    ttl_seconds: Optional[int] = Field(None, description="Time-to-live for cache entries in seconds")
    eviction_policy: str = Field("LRU", description="Cache eviction policy (LRU, FIFO, LFU)")
    compression: bool = Field(False, description="Enable response compression")


class ModelConfigSchema(BaseModel):
    """Enhanced model configuration schema."""
    provider: ProviderType
    model_name: str
    cache: CacheConfigSchema = Field(default_factory=CacheConfigSchema)
    provider_config: ProviderConfigSchema
    temperature: float = Field(0.7, ge=0.0, le=2.0, description="Sampling temperature")
    max_tokens: Optional[int] = Field(None, ge=1, description="Maximum tokens to generate")
    top_p: float = Field(1.0, ge=0.0, le=1.0, description="Nucleus sampling threshold")
    frequency_penalty: float = Field(0.0, ge=-2.0, le=2.0, description="Frequency penalty")
    presence_penalty: float = Field(0.0, ge=-2.0, le=2.0, description="Presence penalty")
    stop_sequences: List[str] = Field(default_factory=list, description="Stop sequences")
    max_retry_time: float = Field(30.0, ge=1.0, description="Maximum time for retries")
    retry_on_rate_limit: bool = Field(True, description="Retry on rate limit errors")


class MonitoringConfigSchema(BaseModel):
    """Monitoring configuration schema."""
    enabled: bool = Field(True, description="Enable monitoring")
    sampling_rate: float = Field(1.0, ge=0.0, le=1.0, description="Sampling rate for metrics")
    metrics: Dict[str, Any] = Field(default_factory=dict, description="Metrics configuration")
    tracing: Dict[str, Any] = Field(default_factory=dict, description="Tracing configuration")
    logging: Dict[str, Any] = Field(default_factory=dict, description="Monitoring logging configuration")


class StreamingConfigSchema(BaseModel):
    """Streaming configuration schema."""
    enabled: bool = Field(True, description="Enable streaming")
    chunk_size: int = Field(100, ge=1, description="Chunk size in tokens")
    buffer_size: int = Field(1024, ge=1, description="Buffer size in bytes")
    timeout: float = Field(30.0, ge=1.0, description="Streaming timeout in seconds")
    max_concurrent_streams: int = Field(10, ge=1, description="Maximum concurrent streams")


class RouterConfigSchema(BaseModel):
    """Router configuration schema."""
    enabled: bool = Field(True, description="Enable router")
    strategy: str = Field("default", description="Routing strategy")
    fallback_model: Optional[str] = Field(None, description="Fallback model name")
    routing_rules: List[Dict[str, Any]] = Field(default_factory=list, description="Routing rules")
    load_balancing: str = Field("round_robin", description="Load balancing strategy")
    health_checks: Dict[str, Any] = Field(default_factory=dict, description="Health check configuration")


class LoggingConfigSchema(BaseModel):
    """Logging configuration schema."""
    level: LogLevel = Field(LogLevel.INFO, description="Log level")
    format: str = Field("[%(asctime)s] %(levelname)s - %(message)s", description="Log format")
    date_format: str = Field("%Y-%m-%d %H:%M:%S", description="Date format")
    handlers: List[str] = Field(default_factory=lambda: ["console"], description="Log handlers")
    file: Optional[str] = Field(None, description="Log file path")
    max_bytes: int = Field(10 * 1024 * 1024, description="Max log file size")
    backup_count: int = Field(5, description="Number of backup files")
    propagate: bool = Field(True, description="Propagate logs to parent loggers")


@dataclass
class Config:
    """Main configuration class for InferenceKit with hot-reloading support."""

    # Core configuration
    project_name: str = "InferenceKit"
    version: str = "1.0.0"
    environment: Environment = Field(Environment.DEVELOPMENT, description="Application environment")
    debug: bool = Field(False, description="Enable debug mode")
    log_config: LoggingConfigSchema = Field(default_factory=LoggingConfigSchema)
    data_dir: str = Field("./data", description="Data directory path")
    config_dir: str = Field("./config", description="Configuration directory path")
    hot_reload: bool = Field(True, description="Enable hot reloading")
    reload_interval: float = Field(10.0, ge=1.0, description="Hot reload interval in seconds")
    profiles: List[str] = Field(default_factory=lambda: ["default"], description="Active profiles")

    # Model configuration
    models: List[ModelConfigSchema] = field(default_factory=list, description="Model configurations")

    # Provider configuration
    providers: Dict[str, ProviderConfigSchema] = field(default_factory=dict, description="Provider configurations")

    # Cache configuration
    cache: CacheConfigSchema = Field(default_factory=CacheConfigSchema, description="Global cache configuration")

    # Monitoring configuration
    monitoring: MonitoringConfigSchema = Field(default_factory=MonitoringConfigSchema, description="Monitoring configuration")

    # Streaming configuration
    streaming: StreamingConfigSchema = Field(default_factory=StreamingConfigSchema, description="Streaming configuration")

    # Router configuration
    router: RouterConfigSchema = Field(default_factory=RouterConfigSchema, description="Router configuration")

    # Security configuration
    security: Dict[str, Any] = field(default_factory=dict, description="Security settings")

    # Advanced configuration
    advanced: Dict[str, Any] = field(default_factory=dict, description="Advanced settings")

    # Internal state
    _lock: threading.RLock = field(default_factory=threading.RLock, init=False, repr=False)
    _watchers: List[Callable] = field(default_factory=list, init=False, repr=False)
    _last_modified: Dict[str, float] = field(default_factory=dict, init=False, repr=False)

    def __post_init__(self):
        """Initialize configuration with validation and normalization."""
        self._validate()
        self._normalize()
        self._setup_logging()

    @root_validator(pre=True)
    def validate_profiles(cls, values):
        """Validate profiles configuration."""
        if not isinstance(values.get("profiles"), list):
            raise ValueError("profiles must be a list of strings")
        return values

    def _validate(self) -> None:
        """Validate configuration."""
        # Validate environment
        if self.environment not in Environment.__members__.values():
            raise ValueError(f"Invalid environment: {self.environment}")

        # Validate data directory
        data_path = Path(self.data_dir)
        if not data_path.exists():
            data_path.mkdir(parents=True, exist_ok=True)

        # Validate config directory
        config_path = Path(self.config_dir)
        if not config_path.exists():
            config_path.mkdir(parents=True, exist_ok=True)

        # Validate models
        model_names = set()
        for model in self.models:
            if not model.model_name.strip():
                raise ValueError("Model name cannot be empty")
            if model.model_name in model_names:
                raise ValueError(f"Duplicate model name: {model.model_name}")
            model_names.add(model.model_name)
            if model.provider not in ProviderType.__members__:
                raise ValueError(f"Invalid provider in model config: {model.provider}")

        # Validate providers
        for provider_name, provider_config in self.providers.items():
            if not provider_name.strip():
                raise ValueError("Provider name cannot be empty")
            if provider_config.base_url and not provider_config.base_url.strip():
                raise ValueError(f"Provider {provider_name} has empty base_url")

        # Validate cache configuration
        if self.cache.max_size < 1:
            raise ValueError("Cache max_size must be at least 1")

        # Validate monitoring configuration
        if self.monitoring.sampling_rate < 0 or self.monitoring.sampling_rate > 1:
            raise ValueError("Monitoring sampling_rate must be between 0 and 1")

        # Validate streaming configuration
        if self.streaming.chunk_size < 1:
            raise ValueError("Streaming chunk_size must be at least 1")

    def _normalize(self) -> None:
        """Normalize configuration."""
        # Normalize paths
        self.data_dir = os.path.abspath(self.data_dir)
        self.config_dir = os.path.abspath(self.config_dir)

        # Normalize model names
        for model in self.models:
            model.model_name = model.model_name.strip()

        # Normalize provider names
        normalized_providers = {}
        for name, config in self.providers.items():
            normalized_name = name.strip().lower()
            normalized_providers[normalized_name] = config
        self.providers = normalized_providers

        # Normalize profiles
        self.profiles = [profile.strip().lower() for profile in self.profiles if profile.strip()]

    def _setup_logging(self) -> None:
        """Setup logging configuration."""
        logging.basicConfig(
            level=getattr(logging, self.log_config.level.value),
            format=self.log_config.format,
            datefmt=self.log_config.date_format
        )

    def get_model_config(self, model_name: str) -> Optional[ModelConfigSchema]:
        """Get configuration for a specific model."""
        for model in self.models:
            if model.model_name == model_name:
                return model
        return None

    def get_provider_config(self, provider_name: str) -> Optional[ProviderConfigSchema]:
        """Get configuration for a specific provider."""
        return self.providers.get(provider_name.lower())

    def get_cache_config(self) -> CacheConfigSchema:
        """Get cache configuration."""
        return self.cache

    def get_monitoring_config(self) -> MonitoringConfigSchema:
        """Get monitoring configuration."""
        return self.monitoring

    def get_streaming_config(self) -> StreamingConfigSchema:
        """Get streaming configuration."""
        return self.streaming

    def get_router_config(self) -> RouterConfigSchema:
        """Get router configuration."""
        return self.router

    def update_config(self, updates: Dict[str, Any]) -> None:
        """Update configuration with new values."""
        with self._lock:
            for key, value in updates.items():
                if hasattr(self, key):
                    setattr(self, key, value)
            self._validate()
            self._normalize()
            self._setup_logging()
            self._notify_watchers()

    def to_dict(self) -> Dict[str, Any]:
        """Convert configuration to dictionary."""
        result = {}
        for key, value in asdict(self).items():
            if key in ["_lock", "_watchers", "_last_modified"]:
                continue
            if isinstance(value, Enum):
                result[key] = value.value
            elif hasattr(value, "model_dump"):
                result[key] = value.model_dump()
            else:
                result[key] = value
        return result

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Config":
        """Create configuration from dictionary."""
        # Convert environment string to enum
        if "environment" in data and isinstance(data["environment"], str):
            data["environment"] = Environment(data["environment"])

        # Convert log level string to enum
        if "log_config" in data and "level" in data["log_config"]:
            data["log_config"]["level"] = LogLevel(data["log_config"]["level"])

        return cls(**data)

    def add_watcher(self, callback: Callable) -> None:
        """Add a configuration change watcher."""
        with self._lock:
            self._watchers.append(callback)

    def _notify_watchers(self) -> None:
        """Notify all watchers of configuration changes."""
        with self._lock:
            for watcher in self._watchers:
                try:
                    watcher(self)
                except Exception as e:
                    logging.error(f"Configuration watcher failed: {e}")

    def start_hot_reload(self) -> None:
        """Start hot reloading of configuration."""
        if not self.hot_reload:
            return

        def reload_worker():
            while True:
                time.sleep(self.reload_interval)
                try:
                    self._check_for_changes()
                except Exception as e:
                    logging.error(f"Hot reload check failed: {e}")

        thread = threading.Thread(target=reload_worker, daemon=True)
        thread.start()

    def _check_for_changes(self) -> None:
        """Check for configuration file changes."""
        config_path = Path(self.config_dir)
        if not config_path.exists():
            return

        for config_file in config_path.glob("*.yaml"):
            self._check_file(config_file)
        for config_file in config_path.glob("*.yml"):
            self._check_file(config_file)
        for config_file in config_path.glob("*.json"):
            self._check_file(config_file)
        for config_file in config_path.glob("*.toml"):
            self._check_file(config_file)

    def _check_file(self, file_path: Path) -> None:
        """Check if a configuration file has changed."""
        try:
            last_modified = file_path.stat().st_mtime
            if file_path.name in self._last_modified:
                if last_modified > self._last_modified[file_path.name]:
                    self._reload_file(file_path)
            self._last_modified[file_path.name] = last_modified
        except Exception as e:
            logging.error(f"Failed to check file {file_path}: {e}")

    def _reload_file(self, file_path: Path) -> None:
        """Reload configuration from file."""
        try:
            new_config = ConfigLoader.load_from_file(str(file_path))
            with self._lock:
                # Merge new config with existing
                current_dict = self.to_dict()
                merged_dict = {**current_dict, **new_config.to_dict()}
                self.update_config(merged_dict)
                logging.info(f"Reloaded configuration from {file_path}")
        except Exception as e:
            logging.error(f"Failed to reload configuration from {file_path}: {e}")


class ConfigLoader:
    """Configuration loader for InferenceKit."""

    DEFAULT_CONFIG_FILES = [
        "./inferencekit.yaml",
        "./inferencekit.yml",
        "./inferencekit.json",
        "./inferencekit.toml",
        "./config/inferencekit.yaml",
        "./config/inferencekit.yml",
        "./config/inferencekit.json",
        "./config/inferencekit.toml",
        "/etc/inferencekit/config.yaml",
        "/etc/inferencekit/config.yml",
        "/etc/inferencekit/config.json",
        "/etc/inferencekit/config.toml",
    ]

    ENVIRONMENT_PREFIX = "INFERENCEKIT_"
    PROFILE_PREFIX = "INFERENCEKIT_PROFILE_"

    @staticmethod
    def _load_environment_variables() -> Dict[str, Any]:
        """Load configuration from environment variables."""
        env_config = {}
        profile_config = defaultdict(dict)

        # Load main environment variables
        prefix_len = len(ConfigLoader.ENVIRONMENT_PREFIX)
        for key, value in os.environ.items():
            if key.startswith(ConfigLoader.ENVIRONMENT_PREFIX):
                config_key = key[prefix_len:].lower()
                env_config[config_key] = ConfigLoader._parse_env_value(config_key, value)

        # Load profile-specific environment variables
        profile_prefix_len = len(ConfigLoader.PROFILE_PREFIX)
        for key, value in os.environ.items():
            if key.startswith(ConfigLoader.PROFILE_PREFIX):
                profile_part, config_key = key[profile_prefix_len:].split("_", 1)
                profile = profile_part.lower()
                profile_config[profile][config_key.lower()] = ConfigLoader._parse_env_value(config_key, value)

        # Merge profile config into main config
        profiles = env_config.get("profiles", [])
        if isinstance(profiles, str):
            profiles = [p.strip() for p in profiles.split(",") if p.strip()]

        for profile in profiles:
            if profile in profile_config:
                env_config.update(profile_config[profile])

        return env_config

    @staticmethod
    def _parse_env_value(key: str, value: str) -> Any:
        """Parse environment variable value to appropriate type."""
        # Convert to appropriate types
        if key.endswith("enabled") or key.endswith("active"):
            return value.lower() in ["true", "1", "yes", "on"]
        elif key.endswith("timeout") or key.endswith("max_retries") or key.endswith("max_size"):
            try:
                return int(value)
            except ValueError:
                return value
        elif key.endswith("threshold") or key.endswith("temperature") or key.endswith("sampling_rate"):
            try:
                return float(value)
            except ValueError:
                return value
        elif key in ["profiles", "providers", "models"]:
            try:
                return json.loads(value)
            except json.JSONDecodeError:
                return value
        else:
            return value

    @staticmethod
    def load_config(config_files: Optional[List[str]] = None,
                   env_config: Optional[Dict[str, Any]] = None) -> Config:
        """Load configuration from files and environment."""
        config_files = config_files or ConfigLoader.DEFAULT_CONFIG_FILES
        env_config = env_config or ConfigLoader._load_environment_variables()

        # Load from files
        file_config = {}
        for file_path in config_files:
            if os.path.exists(file_path):
                try:
                    file_config.update(ConfigLoader.load_from_file(file_path).to_dict())
                    break  # Use the first found config file
                except Exception as e:
                    logging.warning(f"Warning: Failed to load config from {file_path}: {e}")

        # Merge with environment variables
        merged_config = {**file_config, **env_config}

        # Handle profiles
        profiles = merged_config.get("profiles", [])
        if isinstance(profiles, str):
            profiles = [p.strip() for p in profiles.split(",") if p.strip()]

        # Create configuration
        config = Config.from_dict(merged_config)
        config.start_hot_reload()
        return config

    @staticmethod
    def load_from_file(file_path: str) -> Config:
        """Load configuration from file."""
        file_path = os.path.abspath(file_path)
        file_ext = Path(file_path).suffix.lower()

        with open(file_path, 'r') as f:
            if file_ext == '.json':
                data = json.load(f)
            elif file_ext in ['.yaml', '.yml']:
                data = yaml.safe_load(f)
            elif file_ext == '.toml':
                data = toml.load(f)
            else:
                raise ValueError(f"Unsupported file format: {file_ext}")

        return Config.from_dict(data)

    @staticmethod
    def load_from_dict(data: Dict[str, Any]) -> Config:
        """Load configuration from dictionary."""
        return Config.from_dict(data)


class ConfigValidator:
    """Configuration validator for InferenceKit."""

    def __init__(self, config: Config):
        self.config = config

    def validate(self) -> Tuple[bool, List[str]]:
        """Validate the configuration."""
        errors = []

        # Validate core configuration
        if self.config.environment not in Environment.__members__.values():
            errors.append(f"Invalid environment: {self.config.environment}")

        # Validate models
        model_names = set()
        for model in self.config.models:
            if not model.model_name.strip():
                errors.append("Model name cannot be empty")
            if model.model_name in model_names:
                errors.append(f"Duplicate model name: {model.model_name}")
            model_names.add(model.model_name)
            if model.provider not in ProviderType.__members__:
                errors.append(f"Invalid provider in model config: {model.provider}")
            # Validate model-specific settings
            if model.temperature < 0 or model.temperature > 2:
                errors.append(f"Model {model.model_name} has invalid temperature: {model.temperature}")
            if model.max_tokens is not None and model.max_tokens < 1:
                errors.append(f"Model {model.model_name} has invalid max_tokens: {model.max_tokens}")

        # Validate providers
        for provider_name, provider_config in self.config.providers.items():
            if not provider_name.strip():
                errors.append("Provider name cannot be empty")
            if provider_config.base_url and not provider_config.base_url.strip():
                errors.append(f"Provider {provider_name} has empty base_url")
            if provider_config.timeout < 0.1:
                errors.append(f"Provider {provider_name} has invalid timeout: {provider_config.timeout}")

        # Validate cache configuration
        if self.config.cache.max_size < 1:
            errors.append("Cache max_size must be at least 1")
        if self.config.cache.similarity_threshold < 0 or self.config.cache.similarity_threshold > 1:
            errors.append("Cache similarity_threshold must be between 0 and 1")

        # Validate monitoring configuration
        if self.config.monitoring.sampling_rate < 0 or self.config.monitoring.sampling_rate > 1:
            errors.append("Monitoring sampling_rate must be between 0 and 1")

        # Validate streaming configuration
        if self.config.streaming.chunk_size < 1:
            errors.append("Streaming chunk_size must be at least 1")
        if self.config.streaming.max_concurrent_streams < 1:
            errors.append("Streaming max_concurrent_streams must be at least 1")

        # Validate router configuration
        if self.config.router.fallback_model and not self.config.get_model_config(self.config.router.fallback_model):
            errors.append(f"Router fallback_model {self.config.router.fallback_model} not found")

        # Validate security configuration
        if "api_keys" in self.config.security:
            for provider, key in self.config.security["api_keys"].items():
                if not key.strip():
                    errors.append(f"Empty API key for provider: {provider}")

        return len(errors) == 0, errors

    def get_validation_report(self) -> Dict[str, Any]:
        """Get detailed validation report."""
        is_valid, errors = self.validate()
        return {
            "is_valid": is_valid,
            "errors": errors,
            "warnings": self._get_warnings(),
            "summary": f"Configuration validation {'succeeded' if is_valid else 'failed'}" +
                     f" with {len(errors)} error(s)"
        }

    def _get_warnings(self) -> List[str]:
        """Get configuration warnings."""
        warnings = []

        # Check for unused models
        defined_models = {model.model_name for model in self.config.models}
        used_models = set()
        for provider_config in self.config.providers.values():
            if hasattr(provider_config, "model") and provider_config.model:
                used_models.add(provider_config.model)

        unused_models = defined_models - used_models
        if unused_models:
            warnings.append(f"Unused models defined: {', '.join(unused_models)}")

        # Check for default values
        if self.config.environment == Environment.DEVELOPMENT:
            warnings.append("Running in development environment - not suitable for production")

        return warnings


class ConfigManager:
    """Configuration manager for InferenceKit."""

    def __init__(self, config: Config):
        self.config = config
        self.validator = ConfigValidator(config)
        self._setup_validation()

    def _setup_validation(self) -> None:
        """Setup configuration validation."""
        is_valid, errors = self.validator.validate()
        if not is_valid:
            raise ValueError(f"Invalid configuration: {errors}")

    def validate_and_report(self) -> Dict[str, Any]:
        """Validate configuration and return detailed report."""
        return self.validator.get_validation_report()

    def save_config(self, file_path: str) -> None:
        """Save configuration to file."""
        self.config.save_to_file(file_path)

    def update_config(self, updates: Dict[str, Any]) -> None:
        """Update configuration with validation."""
        self.config.update_config(updates)
        self._setup_validation()

    def get_config_summary(self) -> Dict[str, Any]:
        """Get summary of current configuration."""
        return {
            "project": {
                "name": self.config.project_name,
                "version": self.config.version,
                "environment": self.config.environment.value,
                "debug": self.config.debug
            },
            "models": len(self.config.models),
            "providers": len(self.config.providers),
            "cache": {
                "enabled": self.config.cache.enabled,
                "max_size": self.config.cache.max_size
            },
            "monitoring": {
                "enabled": self.config.monitoring.enabled,
                "sampling_rate": self.config.monitoring.sampling_rate
            },
            "profiles": self.config.profiles
        }

    def get_model_details(self, model_name: str) -> Optional[Dict[str, Any]]:
        """Get detailed information about a specific model."""
        model_config = self.config.get_model_config(model_name)
        if not model_config:
            return None

        return {
            "name": model_config.model_name,
            "provider": model_config.provider.value,
            "temperature": model_config.temperature,
            "max_tokens": model_config.max_tokens,
            "cache_enabled": model_config.cache.enabled,
            "provider_config": model_config.provider_config.model_dump()
        }

    def get_provider_details(self, provider_name: str) -> Optional[Dict[str, Any]]:
        """Get detailed information about a specific provider."""
        provider_config = self.config.get_provider_config(provider_name)
        if not provider_config:
            return None

        return {
            "name": provider_name,
            "api_key": "****" if provider_config.api_key else None,
            "base_url": provider_config.base_url,
            "timeout": provider_config.timeout,
            "max_retries": provider_config.max_retries
        }

    def get_all_models(self) -> List[Dict[str, Any]]:
        """Get information about all configured models."""
        return [self.get_model_details(model.model_name) for model in self.config.models]

    def get_all_providers(self) -> List[Dict[str, Any]]:
        """Get information about all configured providers."""
        return [self.get_provider_details(name) for name in self.config.providers.keys()]


# Default configuration for quick setup
DEFAULT_CONFIG = Config(
    project_name="InferenceKit",
    version="1.0.0",
    environment=Environment.DEVELOPMENT,
    debug=True,
    log_config=LoggingConfigSchema(
        level=LogLevel.INFO,
        format="[%(asctime)s] %(levelname)s - %(message)s",
        date_format="%Y-%m-%d %H:%M:%S"
    ),
    data_dir="./data",
    config_dir="./config",
    hot_reload=True,
    reload_interval=10.0,
    profiles=["default"],
    models=[
        ModelConfigSchema(
            provider=ProviderType.OPENAI,
            model_name="gpt-3.5-turbo",
            cache=CacheConfigSchema(enabled=True, max_size=500),
            provider_config=ProviderConfigSchema(
                api_key="your-openai-api-key",
                timeout=10.0,
                max_retries=3
            ),
            temperature=0.7,
            max_tokens=4000,
            top_p=1.0
        ),
        ModelConfigSchema(
            provider=ProviderType.ANTHROPIC,
            model_name="claude-3-haiku",
            cache=CacheConfigSchema(enabled=True, max_size=500),
            provider_config=ProviderConfigSchema(
                api_key="your-anthropic-api-key",
                timeout=10.0,
                max_retries=3
            ),
            temperature=0.7,
            max_tokens=4000,
            top_p=1.0
        )
    ],
    providers={
        "openai": ProviderConfigSchema(
            api_key="your-openai-api-key",
            timeout=10.0,
            max_retries=3
        ),
        "anthropic": ProviderConfigSchema(
            api_key="your-anthropic-api-key",
            timeout=10.0,
            max_retries=3
        )
    },
    cache=CacheConfigSchema(
        enabled=True,
        max_size=1000,
        similarity_threshold=0.8,
        ttl_seconds=3600
    ),
    monitoring=MonitoringConfigSchema(
        enabled=True,
        sampling_rate=1.0,
        metrics={"enabled": True},
        tracing={"enabled": True}
    ),
    streaming=StreamingConfigSchema(
        enabled=True,
        chunk_size=100,
        buffer_size=1024,
        timeout=30.0,
        max_concurrent_streams=10
    ),
    router=RouterConfigSchema(
        enabled=True,
        strategy="default",
        fallback_model="gpt-3.5-turbo",
        routing_rules=[],
        load_balancing="round_robin"
    ),
    security={"api_keys": {}},
    advanced={}
)