"""Application configuration using Pydantic Settings.

This module provides environment-based configuration for the Mantimon TCG backend.
Configuration values can be set via environment variables or .env files.

Environment Detection:
    - dev: Local development (default)
    - staging: Pre-production testing
    - prod: Production environment

Example .env file:
    ENVIRONMENT=dev
    DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/mantimon
    REDIS_URL=redis://localhost:6379/0
    SECRET_KEY=your-secret-key-here

Usage:
    from app.config import settings

    print(settings.database_url)
    print(settings.is_production)
"""

from functools import lru_cache
from typing import Literal

from pydantic import Field, PostgresDsn, RedisDsn, SecretStr, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """Application settings loaded from environment variables.

    All settings can be overridden via environment variables.
    Prefix: None (direct variable names)

    Attributes:
        environment: Current environment (dev/staging/prod).
        debug: Enable debug mode (auto-set based on environment).

        database_url: PostgreSQL connection URL.
        database_pool_size: Connection pool size.
        database_max_overflow: Max overflow connections.

        redis_url: Redis connection URL.
        redis_max_connections: Max Redis connections.

        secret_key: Secret key for JWT signing.
        jwt_algorithm: JWT signing algorithm.
        jwt_expire_minutes: JWT token expiration in minutes.

        google_client_id: Google OAuth client ID.
        google_client_secret: Google OAuth client secret.
        discord_client_id: Discord OAuth client ID.
        discord_client_secret: Discord OAuth client secret.

        cors_origins: Allowed CORS origins.
    """

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

    # Environment
    environment: Literal["dev", "staging", "prod"] = Field(
        default="dev",
        description="Current environment",
    )
    debug: bool = Field(
        default=False,
        description="Enable debug mode",
    )

    # Database (PostgreSQL)
    database_url: PostgresDsn = Field(
        default="postgresql+asyncpg://mantimon:mantimon@localhost:5433/mantimon",
        description="PostgreSQL connection URL",
    )
    database_pool_size: int = Field(
        default=5,
        ge=1,
        le=50,
        description="Database connection pool size",
    )
    database_max_overflow: int = Field(
        default=10,
        ge=0,
        le=100,
        description="Max overflow connections beyond pool size",
    )
    database_echo: bool = Field(
        default=False,
        description="Echo SQL statements (for debugging)",
    )

    # Redis
    redis_url: RedisDsn = Field(
        default="redis://localhost:6380/0",
        description="Redis connection URL",
    )
    redis_max_connections: int = Field(
        default=10,
        ge=1,
        le=100,
        description="Max Redis connections in pool",
    )

    # Security
    secret_key: SecretStr = Field(
        default="dev-secret-key-change-in-production",
        description="Secret key for JWT and other cryptographic operations",
    )
    jwt_algorithm: str = Field(
        default="HS256",
        description="JWT signing algorithm",
    )
    jwt_expire_minutes: int = Field(
        default=30,
        ge=1,
        description="JWT access token expiration in minutes",
    )
    jwt_refresh_expire_days: int = Field(
        default=7,
        ge=1,
        description="JWT refresh token expiration in days",
    )

    # OAuth - Google
    google_client_id: str | None = Field(
        default=None,
        description="Google OAuth 2.0 client ID",
    )
    google_client_secret: SecretStr | None = Field(
        default=None,
        description="Google OAuth 2.0 client secret",
    )

    # OAuth - Discord
    discord_client_id: str | None = Field(
        default=None,
        description="Discord OAuth 2.0 client ID",
    )
    discord_client_secret: SecretStr | None = Field(
        default=None,
        description="Discord OAuth 2.0 client secret",
    )

    # CORS
    cors_origins: list[str] = Field(
        default=["http://localhost:3000", "http://localhost:5173"],
        description="Allowed CORS origins",
    )

    # Base URL (for OAuth callbacks and external links)
    base_url: str = Field(
        default="http://localhost:8000",
        description="Base URL of the API server (for OAuth callbacks)",
    )

    # Game Settings
    turn_timeout_seconds: int = Field(
        default=120,
        ge=30,
        le=600,
        description="Turn timeout in seconds (2 minutes default)",
    )
    game_cache_ttl_seconds: int = Field(
        default=86400,  # 24 hours
        ge=3600,
        le=604800,  # 1 week max
        description="Game state cache TTL in Redis (seconds)",
    )

    # Card Data
    card_data_path: str = Field(
        default="data/cards",
        description="Path to bundled card JSON files",
    )

    # Admin
    admin_api_key: SecretStr | None = Field(
        default=None,
        description="API key for admin endpoints (required in production)",
    )

    @field_validator("debug", mode="before")
    @classmethod
    def set_debug_from_environment(cls, v: bool, info) -> bool:
        """Auto-enable debug in dev environment if not explicitly set."""
        if v is not None:
            return v
        env = info.data.get("environment", "dev")
        return env == "dev"

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

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

    @property
    def database_url_sync(self) -> str:
        """Get synchronous database URL (for Alembic migrations).

        Converts asyncpg:// to psycopg2:// for sync operations.
        """
        url = str(self.database_url)
        return url.replace("postgresql+asyncpg://", "postgresql://")


@lru_cache
def get_settings() -> Settings:
    """Get cached settings instance.

    Uses lru_cache to ensure settings are only loaded once.

    Returns:
        Settings instance loaded from environment.

    Example:
        settings = get_settings()
        print(settings.database_url)
    """
    return Settings()


# Convenience alias for direct import
settings = get_settings()
