"""Configuration settings for the Cadence 🤖 Multi-agents AI Framework.

This module provides comprehensive configuration management for the Cadence framework.
All configuration values can be set via environment variables with the ``CADENCE_`` prefix
(case-insensitive), and field validation is handled by Pydantic.

Key Features:
- Environment variable support with ``CADENCE_`` prefix (case-insensitive)
- Automatic type conversion and validation
- Default values for all settings
- Support for .env files

Example:
    Values can be provided via environment variables with prefix ``CADENCE_``
    (e.g., ``CADENCE_API_PORT=8080``), or from a ``.env`` file.
"""

from typing import List, Optional

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """Application configuration settings with environment variable support.

    All settings can be configured via environment variables with the CADENCE_ prefix:

    Examples:
        export CADENCE_API_PORT=8080
        export CADENCE_DEFAULT_LLM_PROVIDER=anthropic
        export CADENCE_ANTHROPIC_API_KEY=your-key-here
        export CADENCE_DEBUG=true
    """

    # Application settings
    app_name: str = Field(default="Cadence 🤖 Multi-agents AI Framework", description="Application name")
    debug: bool = Field(default=False, description="Enable debug mode")

    # API settings
    api_host: str = Field(default="0.0.0.0", description="API host to bind to")
    api_port: int = Field(default=8000, description="API port to bind to")
    cors_origins: List[str] = Field(default=["*"], description="CORS allowed origins")

    # LLM Provider settings
    default_llm_provider: str = Field(default="openai", description="Default LLM provider")
    openai_api_key: Optional[str] = Field(default=None, description="OpenAI API key")
    anthropic_api_key: Optional[str] = Field(default=None, description="Anthropic API key")
    google_api_key: Optional[str] = Field(default=None, description="Google AI API key")

    # Plugin settings
    plugins_dir: List[str] = Field(
        default=["./plugins/src/cadence_example_plugins"], description="Directories to search for plugins"
    )
    enable_directory_plugins: bool = Field(default=True, description="Enable directory-based plugin discovery")

    # Database settings
    postgres_url: Optional[str] = Field(
        default=None, description="PostgreSQL connection URL (e.g., postgresql+asyncpg://user:pass@localhost/cadence)"
    )
    redis_url: Optional[str] = Field(default="redis://localhost:6379", description="Redis connection URL")
    mongo_url: Optional[str] = Field(default=None, description="MongoDB connection URL")
    cassandra_hosts: Optional[List[str]] = Field(default=None, description="Cassandra cluster hosts")
    mariadb_url: Optional[str] = Field(default=None, description="MariaDB connection URL")

    # Conversation settings
    conversation_storage_backend: str = Field(default="memory", description="Conversation storage backend")
    max_agent_hops: int = Field(default=25, description="Maximum agent hops per conversation")
    graph_recursion_limit: int = Field(default=50, description="Maximum graph recursion depth")

    # Session settings
    session_timeout: int = Field(default=3600, description="Session timeout in seconds")
    max_session_history: int = Field(default=100, description="Maximum conversation history per session")

    # Logging settings
    log_level: str = Field(default="INFO", description="Logging level")
    log_format: str = Field(
        default="%(asctime)s - %(name)s - %(levelname)s - %(message)s", description="Log message format"
    )

    # Security settings
    secret_key: Optional[str] = Field(default=None, description="Secret key for JWT tokens")
    access_token_expire_minutes: int = Field(default=30, description="Access token expiration time")

    # Rate limiting
    rate_limit_requests: int = Field(default=100, description="Rate limit requests per minute")
    rate_limit_window: int = Field(default=60, description="Rate limit window in seconds")

    # Health check settings
    health_check_interval: int = Field(default=30, description="Health check interval in seconds")
    health_check_timeout: int = Field(default=5, description="Health check timeout in seconds")

    # Feature flags
    enable_metrics: bool = Field(default=True, description="Enable metrics collection")
    enable_tracing: bool = Field(default=False, description="Enable distributed tracing")
    enable_profiling: bool = Field(default=False, description="Enable performance profiling")

    # Development settings
    reload_on_change: bool = Field(default=False, description="Auto-reload on file changes")
    enable_hot_reload: bool = Field(default=False, description="Enable hot reload for development")

    # Testing settings
    test_mode: bool = Field(default=False, description="Enable test mode")
    mock_external_services: bool = Field(default=False, description="Mock external services in tests")

    # Performance settings
    worker_processes: int = Field(default=1, description="Number of worker processes")
    max_concurrent_requests: int = Field(default=1000, description="Maximum concurrent requests")
    request_timeout: int = Field(default=30, description="Request timeout in seconds")

    # Monitoring settings
    enable_prometheus: bool = Field(default=False, description="Enable Prometheus metrics")
    metrics_port: int = Field(default=9090, description="Metrics endpoint port")

    # Backup and recovery
    backup_enabled: bool = Field(default=False, description="Enable automatic backups")
    backup_interval: int = Field(default=86400, description="Backup interval in seconds")
    backup_retention_days: int = Field(default=30, description="Backup retention period")

    # Integration settings
    slack_bot_token: Optional[str] = Field(default=None, description="Slack bot token")
    discord_bot_token: Optional[str] = Field(default=None, description="Discord bot token")
    webhook_secret: Optional[str] = Field(default=None, description="Webhook verification secret")

    # Advanced settings
    custom_middleware: List[str] = Field(default=[], description="Custom middleware modules")
    custom_routes: List[str] = Field(default=[], description="Custom route modules")
    environment: str = Field(default="development", description="Environment name")

    model_config = SettingsConfigDict(
        env_file=".env", env_file_encoding="utf-8", case_sensitive=False, env_prefix="CADENCE_", extra="ignore"
    )

    def __post_init__(self):
        """Post-initialization validation and setup."""
        if self.debug:
            self.log_level = "DEBUG"
            self.enable_hot_reload = True
            self.enable_tracing = True

        if self.test_mode:
            self.mock_external_services = True
            self.enable_metrics = False
            self.enable_tracing = False

    @property
    def is_production(self) -> bool:
        """Check if running in production environment."""
        return self.environment.lower() == "production"

    @property
    def is_development(self) -> bool:
        """Check if running in development environment."""
        return self.environment.lower() == "development"

    @property
    def is_testing(self) -> bool:
        """Check if running in testing environment."""
        return self.environment.lower() == "testing"

    def get_database_url(self, backend: str) -> Optional[str]:
        """Get database URL for specified backend."""
        backend_map = {
            "postgresql": self.postgres_url,
            "redis": self.redis_url,
            "mongodb": self.mongo_url,
            "cassandra": self.cassandra_hosts,
            "mariadb": self.mariadb_url,
        }
        return backend_map.get(backend.lower())

    def validate_llm_provider(self, provider: str) -> bool:
        """Validate if the specified LLM provider is configured."""
        if provider.lower() == "openai":
            return bool(self.openai_api_key)
        elif provider.lower() == "anthropic":
            return bool(self.anthropic_api_key)
        elif provider.lower() == "google":
            return bool(self.google_api_key)
        else:
            return False

    @staticmethod
    def get_default_provider_llm_model(provider: str) -> str:
        """Get the default model name for the configured LLM provider."""
        if provider == "openai":
            return "gpt-4o-mini"
        elif provider == "anthropic":
            return "claude-3-5-sonnet-20241022"
        elif provider == "google":
            return "gemini-1.5-flash"
        else:
            return "gpt-4o-mini"  # fallback

    def get_finalizer_provider_llm_model(self, provider: str) -> str:
        """Get the model name for the finalizer LLM provider."""
        return self.get_default_provider_llm_model(provider)

    def get_api_key_for_provider(self, provider: str) -> Optional[str]:
        """Get the API key for a specific provider."""
        provider = provider.lower()
        if provider == "openai":
            return self.openai_api_key
        elif provider == "anthropic":
            return self.anthropic_api_key
        elif provider == "google":
            return self.google_api_key
        else:
            return None

    def get_provider_extra_params(self, provider: str) -> dict:
        """Get extra parameters for a specific provider."""
        return {}

    @property
    def default_llm_temperature(self) -> float:
        """Get the default temperature for LLM models."""
        return 0.7

    @property
    def default_llm_context_window(self) -> int:
        """Get the default context window size for LLM models."""
        return 4096

    @property
    def coordinator_llm_provider(self) -> Optional[str]:
        """Get the LLM provider for the coordinator. Falls back to default if None."""
        return None

    @property
    def coordinator_temperature(self) -> float:
        """Get the temperature for the coordinator LLM."""
        return 0.7

    @property
    def coordinator_max_tokens(self) -> int:
        """Get the max tokens for the coordinator LLM."""
        return 4096

    @property
    def suspend_llm_provider(self) -> Optional[str]:
        """Get the LLM provider for the suspend node. Falls back to default if None."""
        return None

    @property
    def suspend_temperature(self) -> float:
        """Get the temperature for the suspend node LLM."""
        return 0.5

    @property
    def suspend_max_tokens(self) -> int:
        """Get the max tokens for the suspend node LLM."""
        return 1024

    @property
    def finalizer_llm_provider(self) -> Optional[str]:
        """Get the LLM provider for the finalizer. Falls back to default if None."""
        return None

    @property
    def finalizer_temperature(self) -> float:
        """Get the temperature for the finalizer LLM."""
        return 0.3

    @property
    def finalizer_max_tokens(self) -> int:
        """Get the max tokens for the finalizer LLM."""
        return 1024


# Global settings instance
settings = Settings()

# Convenience imports
__all__ = ["Settings", "settings"]
