"""Environment-derived configuration.

Loaded once at process start. Every module that needs a value pulls it from
here rather than re-reading os.environ, so there is one obvious place to
look when a setting is missing.
"""
from __future__ import annotations

import os
from dataclasses import dataclass, field
from pathlib import Path

from dotenv import load_dotenv

load_dotenv()


def _required(name: str) -> str:
    value = os.environ.get(name, "").strip()
    if not value:
        raise RuntimeError(f"Required environment variable {name} is not set")
    return value


def _optional(name: str, default: str = "") -> str:
    return os.environ.get(name, default).strip()


@dataclass
class Config:
    gitea_url: str
    gitea_bot_user: str
    gitea_bot_token: str
    gitea_org: str
    registry_repo: str
    oauth_client_id: str
    oauth_client_secret: str
    app_url: str
    secret_key: str
    database_path: Path
    owner_gitea_login: str
    webhook_secret: str
    enabled_models: list[str] = field(default_factory=list)
    anthropic_api_key: str = ""
    google_api_key: str = ""
    openai_api_key: str = ""
    default_project_id: str = ""

    @property
    def redirect_uri(self) -> str:
        return f"{self.app_url}/auth/callback"

    @property
    def registry_repo_full(self) -> str:
        return f"{self.gitea_org}/{self.registry_repo}"


def load_config() -> Config:
    database_path = Path(_optional("DATABASE_PATH", "data/rfc-app.db")).resolve()
    database_path.parent.mkdir(parents=True, exist_ok=True)

    enabled = [m.strip() for m in _optional("ENABLED_MODELS", "claude").split(",") if m.strip()]

    # v0.18.0: `GITEA_WEBHOOK_SECRET` is now mandatory (per the
    # email + webhook hygiene proposal). An empty value used to
    # silently accept unsigned webhook POSTs — that was the
    # invisible-failure shape the proposal targets. Now the
    # framework refuses to start when the secret is empty unless
    # the operator opts into the dev-bypass with
    # `RFC_APP_INSECURE_WEBHOOKS=1`. Local-dev deployments without
    # a wired Gitea hook set the bypass; production MUST NOT.
    insecure_webhooks = os.environ.get("RFC_APP_INSECURE_WEBHOOKS", "").strip() == "1"
    if insecure_webhooks:
        webhook_secret = _optional("GITEA_WEBHOOK_SECRET")
    else:
        webhook_secret = _required("GITEA_WEBHOOK_SECRET")

    return Config(
        gitea_url=_required("GITEA_URL").rstrip("/"),
        gitea_bot_user=_required("GITEA_BOT_USER"),
        gitea_bot_token=_required("GITEA_BOT_TOKEN"),
        gitea_org=_required("GITEA_ORG"),
        registry_repo=_required("REGISTRY_REPO"),
        oauth_client_id=_required("OAUTH_CLIENT_ID"),
        oauth_client_secret=_required("OAUTH_CLIENT_SECRET"),
        app_url=_optional("APP_URL", "http://localhost:8000").rstrip("/"),
        secret_key=_required("SECRET_KEY"),
        database_path=database_path,
        owner_gitea_login=_optional("OWNER_GITEA_LOGIN"),
        webhook_secret=webhook_secret,
        enabled_models=enabled,
        anthropic_api_key=_optional("ANTHROPIC_API_KEY"),
        google_api_key=_optional("GOOGLE_API_KEY"),
        openai_api_key=_optional("OPENAI_API_KEY"),
        default_project_id=_optional("DEFAULT_PROJECT_ID"),
    )
