"""
Application settings loaded from environment variables.

Uses pydantic-settings to read from .env file with type validation.
All settings are accessible via the module-level `settings` singleton.
"""

from pydantic import Field, field_validator, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """
    Central configuration for Munal LMS.

    Environment variables are loaded from a .env file at the project root.
    Variable names are case-insensitive.
    """

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

    # ── Application ───────────────────────────────────────────────────────────
    APP_ENV: str = "development"
    APP_DEBUG: bool = True
    APP_NAME: str = "Munal LMS API"
    APP_VERSION: str = "0.1.0"
    APP_SECRET_KEY: str = "change-me-in-production"
    APP_ALLOWED_HOSTS: list[str] = []
    APP_ALLOWED_ORIGINS: list[str] = ["http://localhost:5173"]

    @field_validator("APP_ALLOWED_ORIGINS", mode="before")
    @classmethod
    def parse_cors_origins(cls, v: str | list[str]) -> list[str]:
        """Allow comma-separated string or list for CORS origins."""
        if isinstance(v, str):
            return [origin.strip() for origin in v.split(",")]
        return v

    # ── Database ──────────────────────────────────────────────────────────────
    DATABASE_POOL_SIZE: int = Field(default=5, ge=1, le=50)
    DATABASE_MAX_OVERFLOW: int = Field(default=5, ge=0, le=50)
    DATABASE_URL: str = "postgresql+asyncpg://munal:munal_dev_pass@localhost:5432/munal_lms"

    # ── JWT ───────────────────────────────────────────────────────────────────
    JWT_SECRET_KEY: str = "change-me-jwt-secret"
    JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
    JWT_REFRESH_TOKEN_EXPIRE_DAYS: int = 7
    JWT_ALGORITHM: str = "HS256"

    # ── File Storage (Local Filesystem) ───────────────────────────────────────
    LOCAL_STORAGE_PATH: str = "./storage"

    # ── SMS Gateway ───────────────────────────────────────────────────────────
    SMS_API_URL: str = "https://api.sparrowsms.com/v2/sms"
    SMS_API_TOKEN: str = ""
    SMS_SENDER_ID: str = "MunalLab"

    # ── Client Link Pages ─────────────────────────────────────────────────────
    CLIENT_APP_BASE_URL: str = "http://localhost:5173"
    CLIENT_TOKEN_TTL_HOURS: int = 72

    # ── Email ─────────────────────────────────────────────────────────────────
    SMTP_HOST: str = "smtp.gmail.com"
    SMTP_PORT: int = 587
    SMTP_USER: str = ""
    SMTP_PASSWORD: str = ""
    SMTP_FROM: str = "noreply@munallab.com"
    SMTP_FROM_NAME: str = "Munal LMS"
    SMTP_TLS: bool = True
    SMTP_SSL: bool = False

    # ── Observability ─────────────────────────────────────────────────────────
    SENTRY_DSN: str = ""
    PROMETHEUS_ENABLED: bool = True

    # ── Rate Limiting ─────────────────────────────────────────────────────────
    RATE_LIMIT_ENABLED: bool = True

    @model_validator(mode="after")
    def validate_production(self) -> "Settings":
        """Fail closed for unsafe production settings without echoing secrets."""
        if self.is_production:
            if self.APP_DEBUG or not self.RATE_LIMIT_ENABLED:
                raise ValueError("Production requires APP_DEBUG=false and rate limiting enabled.")
            for key in (self.APP_SECRET_KEY, self.JWT_SECRET_KEY):
                if len(key) < 32 or key.startswith("change-me"):
                    raise ValueError("Production requires unique secret keys of at least 32 characters.")
            if not self.APP_ALLOWED_ORIGINS or any(
                not origin.startswith("https://") or "*" in origin for origin in self.APP_ALLOWED_ORIGINS
            ):
                raise ValueError("Production CORS origins must be explicit HTTPS origins.")
            if not self.APP_ALLOWED_HOSTS or any("*" in host for host in self.APP_ALLOWED_HOSTS):
                raise ValueError("Production requires explicit APP_ALLOWED_HOSTS.")
            if not self.CLIENT_APP_BASE_URL.startswith("https://"):
                raise ValueError("Production patient links require an HTTPS frontend URL.")
        return self

    # ── Derived helpers ───────────────────────────────────────────────────────
    @property
    def is_production(self) -> bool:
        return self.APP_ENV.lower() == "production"

    @property
    def is_development(self) -> bool:
        return self.APP_ENV == "development"

    @property
    def is_testing(self) -> bool:
        return self.APP_ENV.lower() in ("test", "testing")

    @property
    def effective_smtp_from(self) -> str:
        """Use the authenticated SMTP user as From when no custom sender is set (required by Gmail)."""
        user = self.SMTP_USER.strip()
        default_from = "noreply@munallab.com"
        if self.SMTP_FROM.strip() and self.SMTP_FROM.strip() != default_from:
            return self.SMTP_FROM.strip()
        if user and "@" in user:
            return user
        return default_from

    @property
    def effective_smtp_password(self) -> str:
        """Remove visual grouping whitespace from Gmail App Passwords."""
        return "".join(self.SMTP_PASSWORD.split())

    @property
    def smtp_credentials_are_placeholder(self) -> bool:
        """True when .env still contains example SMTP values — no real mail will be sent."""
        user = self.SMTP_USER.strip().lower()
        password = self.effective_smtp_password.lower()
        if not user or not password:
            return True
        if "yourdomain.com" in user or "example.com" in user:
            return True
        if "your-app-password" in password or password == "password":
            return True
        return False


# Module-level singleton — import this everywhere
settings = Settings()
