import os
from dataclasses import dataclass
from pathlib import Path


DEFAULT_SQLITE_PATH = (Path(__file__).resolve().parents[2] / "data_entry_app.db").as_posix()
DEFAULT_DATABASE_URL = f"sqlite:///{DEFAULT_SQLITE_PATH}"


DEFAULT_CORS_ALLOW_ORIGIN_REGEX = (
    r"^https?://("
    r"localhost|127\.0\.0\.1|"
    r"10\.\d{1,3}\.\d{1,3}\.\d{1,3}|"
    r"192\.168\.\d{1,3}\.\d{1,3}|"
    r"172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}"
    r")(:\d+)?$"
)


def _parse_csv_env(value: str) -> tuple[str, ...]:
    return tuple(part.strip() for part in value.split(",") if part.strip())


def _env_flag(name: str, default: bool = False) -> bool:
    value = os.getenv(name)
    if value is None:
        return default
    return value.strip().lower() in {"1", "true", "yes", "on"}


@dataclass(frozen=True)
class Settings:
    app_name: str
    app_env: str
    host: str
    port: int
    log_level: str
    log_verbose: bool
    database_url: str
    client_name: str
    client_email: str
    client_password: str
    client_tenant_id: str
    admin_name: str
    admin_email: str
    admin_password: str
    auth_secret: str
    cors_allow_origins: tuple[str, ...]
    cors_allow_origin_regex: str
    session_ttl_seconds: int
    session_cookie_name: str
    admin_session_cookie_name: str
    session_cookie_secure: bool
    session_cookie_samesite: str
    session_cookie_domain: str | None
    request_body_max_bytes: int
    login_rate_limit_attempts: int
    login_rate_limit_window_seconds: int
    trusted_hosts: tuple[str, ...]
    docs_enabled: bool
    # Static API key for the read-only Power BI / external data API (`/api/v1`).
    # Blank disables the API entirely (every request returns 503).
    powerbi_api_key: str
    # Tenant the Power BI API reads from. Defaults to the costing client tenant
    # (where internal staff store throughput), so a single key serves Irwin.
    powerbi_tenant_id: str

    @classmethod
    def from_env(cls) -> "Settings":
        settings = cls(
            app_name=os.getenv("APP_NAME", "Hunter App"),
            app_env=os.getenv("APP_ENV", os.getenv("ENVIRONMENT", "development")),
            host=os.getenv("HOST", "0.0.0.0"),
            port=int(os.getenv("PORT", "8000")),
            log_level=os.getenv("LOG_LEVEL", "DEBUG" if os.getenv("LOG_VERBOSE") in {"1", "true", "TRUE", "yes", "on"} else "INFO"),
            log_verbose=_env_flag("LOG_VERBOSE"),
            # Keep the default SQLite location stable regardless of the current
            # working directory so local dev does not silently fork data into
            # multiple `data_entry_app.db` files.
            database_url=os.getenv("DATABASE_URL", DEFAULT_DATABASE_URL),
            client_name=os.getenv("CLIENT_NAME", "Hunter Premium Produce"),
            client_email=os.getenv("CLIENT_EMAIL", "operator@example.com"),
            client_password=os.getenv("CLIENT_PASSWORD", "changeme"),
            client_tenant_id=os.getenv("CLIENT_TENANT_ID", "hunter-premium-produce"),
            admin_name=os.getenv("ADMIN_NAME", "Lean 101"),
            admin_email=os.getenv("ADMIN_EMAIL", "admin@lean101.local"),
            admin_password=os.getenv("ADMIN_PASSWORD", "lean101-admin"),
            auth_secret=os.getenv("AUTH_SECRET", "lean-101-local-dev-secret"),
            cors_allow_origins=_parse_csv_env(
                os.getenv(
                    "CORS_ALLOW_ORIGINS",
                    "http://localhost:5173,http://localhost:5174,http://127.0.0.1:5173,http://127.0.0.1:5174",
                )
            ),
            cors_allow_origin_regex=os.getenv("CORS_ALLOW_ORIGIN_REGEX", DEFAULT_CORS_ALLOW_ORIGIN_REGEX),
            session_ttl_seconds=int(os.getenv("SESSION_TTL_SECONDS", str(60 * 60 * 12))),
            session_cookie_name=os.getenv("SESSION_COOKIE_NAME", "client_session"),
            admin_session_cookie_name=os.getenv("ADMIN_SESSION_COOKIE_NAME", "admin_session"),
            session_cookie_secure=_env_flag("SESSION_COOKIE_SECURE"),
            session_cookie_samesite=os.getenv("SESSION_COOKIE_SAMESITE", "lax").lower(),
            session_cookie_domain=os.getenv("SESSION_COOKIE_DOMAIN", "").strip() or None,
            request_body_max_bytes=int(os.getenv("REQUEST_BODY_MAX_BYTES", str(1024 * 1024))),
            login_rate_limit_attempts=int(os.getenv("LOGIN_RATE_LIMIT_ATTEMPTS", "8")),
            login_rate_limit_window_seconds=int(os.getenv("LOGIN_RATE_LIMIT_WINDOW_SECONDS", "300")),
            trusted_hosts=_parse_csv_env(os.getenv("TRUSTED_HOSTS", "localhost,127.0.0.1,testserver")),
            docs_enabled=_env_flag("DOCS_ENABLED", default=os.getenv("APP_ENV", os.getenv("ENVIRONMENT", "development")).lower() != "production"),
            powerbi_api_key=os.getenv("POWERBI_API_KEY", "").strip(),
            powerbi_tenant_id=os.getenv("POWERBI_TENANT_ID", os.getenv("CLIENT_TENANT_ID", "hunter-premium-produce")).strip(),
        )
        settings._validate()
        return settings

    def _validate(self) -> None:
        if self.session_cookie_samesite not in {"lax", "strict", "none"}:
            raise ValueError("SESSION_COOKIE_SAMESITE must be one of: lax, strict, none")

        is_production = self.app_env.lower() == "production"
        if not is_production:
            return

        if self.client_password in {"changeme", "", "replace-with-strong-password"}:
            raise ValueError("CLIENT_PASSWORD must be set to a non-default value in production")
        if self.admin_password in {"lean101-admin", "", "replace-with-strong-password"}:
            raise ValueError("ADMIN_PASSWORD must be set to a non-default value in production")
        if self.auth_secret in {"lean-101-local-dev-secret", "change-me-in-production", "", "replace-with-a-long-random-secret"}:
            raise ValueError("AUTH_SECRET must be set to a strong production secret")
        if len(self.auth_secret) < 32:
            raise ValueError("AUTH_SECRET must be at least 32 characters in production")
        if not self.session_cookie_secure:
            raise ValueError("SESSION_COOKIE_SECURE must be enabled in production")
        if not self.cors_allow_origins:
            raise ValueError("CORS_ALLOW_ORIGINS must explicitly list production origins")
        if "localhost" in ",".join(self.cors_allow_origins).lower():
            raise ValueError("CORS_ALLOW_ORIGINS cannot include localhost in production")
        if self.cors_allow_origin_regex == DEFAULT_CORS_ALLOW_ORIGIN_REGEX:
            raise ValueError("CORS_ALLOW_ORIGIN_REGEX must be overridden or blank in production")
        if self.docs_enabled:
            raise ValueError("DOCS_ENABLED must be false in production")


settings = Settings.from_env()
