"""Centralized configuration management for Meta Ads MCP Server."""

from __future__ import annotations

from typing import Optional
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """Centralized configuration for Meta Ads MCP Server.
    
    All configuration is loaded from environment variables with optional .env file support.
    """
    
    # Meta API Configuration
    meta_access_token: Optional[str] = None
    meta_app_id: Optional[str] = None
    meta_app_secret: Optional[str] = None
    meta_default_ad_account_id: Optional[str] = None
    meta_default_business_id: Optional[str] = None
    meta_api_version: str = "v24.0"
    meta_graph_base_url: str = "https://graph.facebook.com"
    meta_api_timeout_seconds: float = 30.0
    meta_max_concurrency: int = 10
    
    # OAuth Configuration
    meta_oauth_scopes: str = "ads_management,ads_read,business_management,pages_read_engagement,pages_show_list,read_insights"
    meta_token_cache_path: str = "~/.config/meta-ads-mcp/token.json"
    meta_login_timeout_seconds: int = 300
    
    # Server Configuration
    server_name: str = "meta-ads-mcp"
    log_level: str = "INFO"
    
    # Feature Flags
    cache_enabled: bool = False
    rate_limiting_enabled: bool = True
    
    # Cache Configuration (Redis)
    redis_url: str = "redis://localhost:6379/0"
    cache_default_ttl: int = 300
    
    # Observability
    prometheus_port: int = 9090
    otel_exporter_otlp_endpoint: Optional[str] = None
    sentry_dsn: Optional[str] = None
    
    # Hosted Mode Configuration
    hosted_mode: bool = False
    auth_broker_url: Optional[str] = None
    auth_broker_api_key: Optional[str] = None
    auth_broker_timeout_seconds: float = 10.0
    jwt_public_key: Optional[str] = None
    jwt_algorithm: str = "HS256"
    jwt_issuer: str = "meta-ads-auth-broker"
    jwt_audience: Optional[str] = None
    
    # Transport Configuration
    transport_type: str = "stdio"  # stdio, http, websocket
    http_host: str = "0.0.0.0"
    http_port: int = 8080
    
    # Performance Configuration
    connection_pool_size: int = 10
    request_timeout: float = 30.0
    max_retries: int = 3
    retry_backoff_factor: float = 2.0
    
    # Licensing
    license_key: Optional[str] = None

    # Resilience Configuration
    circuit_breaker_enabled: bool = True
    circuit_breaker_failure_threshold: int = 5
    circuit_breaker_timeout: float = 60.0
    circuit_breaker_recovery_timeout: float = 30.0
    
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
        extra="ignore",
    )
    
    def validate_config(self) -> None:
        """Validate configuration and raise errors for invalid states."""
        if self.hosted_mode:
            # Hosted mode delegates Meta access token management to auth broker.
            if not self.auth_broker_url:
                raise ValueError("AUTH_BROKER_URL must be set when HOSTED_MODE is true")
            if not self.auth_broker_api_key:
                raise ValueError("AUTH_BROKER_API_KEY must be set when HOSTED_MODE is true")
            if not self.jwt_public_key:
                raise ValueError(
                    "JWT_PUBLIC_KEY must be set when HOSTED_MODE is true "
                    "(for HS256 this should be the shared signing secret)"
                )
        else:
            # Local mode requires direct token or OAuth app credentials.
            if not self.meta_access_token and not (self.meta_app_id and self.meta_app_secret):
                raise ValueError(
                    "Either META_ACCESS_TOKEN or both META_APP_ID and META_APP_SECRET must be set"
                )
        
        # Check transport configuration
        if self.transport_type not in ("stdio", "http", "websocket"):
            raise ValueError(f"Invalid transport type: {self.transport_type}")
        
        # Check cache configuration
        if self.cache_enabled and not self.redis_url:
            raise ValueError("REDIS_URL must be set when CACHE_ENABLED is true")
    
    def get_meta_oauth_scopes_list(self) -> list[str]:
        """Get OAuth scopes as a list."""
        return [scope.strip() for scope in self.meta_oauth_scopes.split(",") if scope.strip()]


# Global settings instance
_settings: Optional[Settings] = None


def get_settings() -> Settings:
    """Get the global settings instance.
    
    Returns:
        Settings: The global settings instance
        
    Raises:
        RuntimeError: If settings haven't been initialized
    """
    global _settings
    if _settings is None:
        raise RuntimeError(
            "Settings not initialized. Call initialize_settings() first."
        )
    return _settings


def initialize_settings(validate: bool = True) -> Settings:
    """Initialize the global settings instance.
    
    Args:
        validate: Whether to validate the configuration
        
    Returns:
        Settings: The initialized settings instance
        
    Raises:
        ValueError: If configuration is invalid and validate=True
    """
    global _settings
    _settings = Settings()
    
    if validate:
        _settings.validate_config()
    
    return _settings


def reset_settings() -> None:
    """Reset the global settings instance (mainly for testing)."""
    global _settings
    _settings = None

