from functools import lru_cache
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field


class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore"
    )

    APP_NAME: str = "Audit_Firm_v2.0.3.6"
    ENV: str = "dev"
    DEBUG: bool = True
    SECRET_KEY: str = "change-me-to-a-long-random-string"
    # Separate high-entropy key for tenant-scoped credential encryption. Never rotate without a re-encryption plan.
    VAULT_MASTER_KEY: str = ""

    COOKIE_SECURE: bool = False
    COOKIE_SAMESITE: str = "lax"
    COOKIE_SESSION_NAME: str = "af2sid"

    DB_BACKEND: str = Field(default="sqlite", description="sqlite|postgres")

    SQLITE_COMMON_PATH: str = "./data/common.db"

    PG_HOST: str = "127.0.0.1"
    PG_PORT: int = 5432
    PG_USER: str = "postgres"
    PG_PASSWORD: str = "postgres"
    PG_DB_COMMON: str = "audit_common"

    DEFAULT_TENANT_CODE: str = "default"
    DEFAULT_BRANCH_CODE: str = "main"
    DEFAULT_YEAR_CODE: str = "2025-26"
    DEFAULT_TIMEZONE: str = "Asia/Kolkata"

    # Public base URL used for email links such as invite and password reset.
    # In Coolify production set this to https://your-erp-domain.
    ERP_PUBLIC_BASE_URL: str = "http://localhost:8000"

    # Print OTP to server logs only in local/dev troubleshooting. Keep false in UAT/production.
    DEV_AUTH_OTP_PRINT: bool = False

    # Context headers are disabled by default for public deployments.
    # When disabled, browser/client supplied X-Tenant-Code, X-Branch-Code,
    # and X-Year-Code are ignored. Enable only for trusted internal runners
    # or reverse proxies that also restrict/strip external request headers.
    TRUST_CONTEXT_HEADERS: bool = False
    TRUST_CONTEXT_HEADER_HOSTS: str = "127.0.0.1,localhost,::1"
    CONTEXT_HEADER_SECRET: str = ""

    # JWT Configuration
    JWT_ISSUER: str = "Audit_Firm_v2.0.3.6"
    JWT_AUDIENCE: str = "audit_firm_clients"
    JWT_ACCESS_MINUTES: int = 15
    JWT_REFRESH_DAYS: int = 30

    # Bootstrap Admin
    BOOTSTRAP_ADMIN_EMAIL: str = "admin@auditfirm.local"
    BOOTSTRAP_ADMIN_PASSWORD: str = "ChangeMe@123"

    INVITE_TOKEN_HOURS: int = 72
    PASSWORD_RESET_HOURS: int = 2
    PASSWORD_MIN_LENGTH: int = 8


@lru_cache
def get_settings() -> Settings:
    s = Settings()

    # Normalize cookie values
    s.COOKIE_SAMESITE = (s.COOKIE_SAMESITE or "lax").lower()
    if s.COOKIE_SAMESITE not in {"lax", "strict", "none"}:
        s.COOKIE_SAMESITE = "lax"

    return s