"""
FastAPI configuration — the "no settings.py" seam.

Builds the shared core's `AuthConfig` (JWT + MWT) and a `CacheOrchestrator`
from environment variables, overridable per-app via `app.state.mizan_config`.

Env:
    MIZAN_CACHE_SECRET      HMAC cache signing key (enables origin cache)
    MIZAN_CACHE_REDIS_URL   Redis URL (else in-memory cache)
    MIZAN_MWT_SECRET        MWT signing key
    MIZAN_MWT_AUDIENCE      MWT audience (default "mizan")
    JWT_PRIVATE_KEY         JWT signing key (enables bearer-JWT auth)
    JWT_PUBLIC_KEY          JWT verify key (default: private key, HS256)
    JWT_ALGORITHM           default "HS256"
    JWT_ACCESS_TOKEN_EXPIRES_IN / JWT_REFRESH_TOKEN_EXPIRES_IN
"""

from __future__ import annotations

import os
from dataclasses import dataclass

from mizan_core.auth import AuthConfig, JWTConfig
from mizan_core.cache.backend import CacheBackend, MemoryCache
from mizan_core.dispatch import CacheOrchestrator


@dataclass(frozen=True)
class MizanConfig:
    auth: AuthConfig
    cache: CacheOrchestrator


def _cache_backend(secret: str | None, redis_url: str | None) -> CacheBackend | None:
    if not secret:
        return None
    if redis_url:
        from mizan_core.cache.backend import RedisCache
        return RedisCache(redis_url)
    return MemoryCache()


def _jwt_config() -> JWTConfig | None:
    key = os.getenv("JWT_PRIVATE_KEY")
    if not key:
        return None
    return JWTConfig(
        private_key=key,
        public_key=os.getenv("JWT_PUBLIC_KEY", key),
        algorithm=os.getenv("JWT_ALGORITHM", "HS256"),
        access_token_expires_in=int(os.getenv("JWT_ACCESS_TOKEN_EXPIRES_IN", "300")),
        refresh_token_expires_in=int(os.getenv("JWT_REFRESH_TOKEN_EXPIRES_IN", "604800")),
    )


def from_env() -> MizanConfig:
    secret = os.getenv("MIZAN_CACHE_SECRET")
    backend = _cache_backend(secret, os.getenv("MIZAN_CACHE_REDIS_URL"))
    auth = AuthConfig(
        jwt=_jwt_config(),
        mwt_secret=os.getenv("MIZAN_MWT_SECRET"),
        mwt_audience=os.getenv("MIZAN_MWT_AUDIENCE", "mizan"),
    )
    return MizanConfig(auth=auth, cache=CacheOrchestrator(backend, secret))


def get_config(request) -> MizanConfig:
    """Per-app config: `app.state.mizan_config` if set, else built from env (cached)."""
    app = getattr(request, "app", None)
    state = getattr(app, "state", None)
    override = getattr(state, "mizan_config", None) if state is not None else None
    if override is not None:
        return override
    global _DEFAULT
    if _DEFAULT is None:
        _DEFAULT = from_env()
    return _DEFAULT


_DEFAULT: MizanConfig | None = None
