"""
Feature flags for the kvict Proxy (B2C).

Best practices:
- Central definition: all proxy feature flags live here.
- Environment-driven: read from PROXY_FEATURE_* or PROXY_*_ENABLED env vars.
- Default off for new features: opt-in to avoid surprising behavior.
- Typed and documented: each flag has type, default, and doc.
- Testable: use set_feature_flags() in tests to override.
- No business logic: flags are booleans; logic stays in app/cache/circuit_breaker.
"""

from __future__ import annotations

import os
from dataclasses import MISSING, dataclass, field
from typing import Any, Dict


def _parse_bool(value: str | None, default: bool) -> bool:
    """Parse env string to bool. True for 'true', '1', 'yes'; False otherwise."""
    if value is None or value == "":
        return default
    return value.strip().lower() in ("true", "1", "yes")


@dataclass(frozen=True)
class ProxyFeatureFlags:
    """
    Proxy (B2C) feature flags.

    All flags are read from environment at construction time. Use get_feature_flags()
    to obtain the singleton instance.
    """

    # -------------------------------------------------------------------------
    # Existing behavior (default on for backward compatibility)
    # -------------------------------------------------------------------------

    circuit_breaker_enabled: bool = field(
        default=True,
        metadata={
            "env": "PROXY_FEATURE_CIRCUIT_BREAKER",
            "doc": "Serve stale cache when provider is degraded; disable to always forward.",
        },
    )

    # -------------------------------------------------------------------------
    # New / optional features (default off)
    # -------------------------------------------------------------------------

    semantic_cache_enabled: bool = field(
        default=False,
        metadata={
            "env": "PROXY_SEMANTIC_CACHE_ENABLED",
            "doc": "Allow cache hits for semantically similar requests (embedding-based).",
        },
    )

    model_routing_enabled: bool = field(
        default=False,
        metadata={
            "env": "PROXY_MODEL_ROUTING_ENABLED",
            "doc": "Route requests by complexity to cheaper/faster or premium models.",
        },
    )

    llm_judge_enabled: bool = field(
        default=False,
        metadata={
            "env": "PROXY_LLM_JUDGE_ENABLED",
            "doc": "Use a small LLM to pick best cached response among semantic candidates.",
        },
    )

    llm_router_enabled: bool = field(
        default=False,
        metadata={
            "env": "PROXY_LLM_ROUTER_ENABLED",
            "doc": "Use a small LLM to choose model tier for ambiguous requests.",
        },
    )

    @classmethod
    def from_env(cls) -> ProxyFeatureFlags:
        """Build flags from current environment. Used by get_feature_flags()."""
        values: Dict[str, bool] = {}
        for name, f in cls.__dataclass_fields__.items():
            if "env" in f.metadata:
                default = f.default if f.default is not MISSING else False
                env_key = f.metadata["env"]
                values[name] = _parse_bool(os.getenv(env_key), default)
        return cls(**values)

    def to_dict(self) -> Dict[str, Any]:
        """For logging and /health or config endpoints."""
        return {
            "circuit_breaker_enabled": self.circuit_breaker_enabled,
            "semantic_cache_enabled": self.semantic_cache_enabled,
            "model_routing_enabled": self.model_routing_enabled,
            "llm_judge_enabled": self.llm_judge_enabled,
            "llm_router_enabled": self.llm_router_enabled,
        }


# Singleton and test override
_flags: ProxyFeatureFlags | None = None


def get_feature_flags() -> ProxyFeatureFlags:
    """Return the global proxy feature flags (from env, cached)."""
    global _flags
    if _flags is None:
        _flags = ProxyFeatureFlags.from_env()
    return _flags


def set_feature_flags(flags: ProxyFeatureFlags | None) -> None:
    """
    Override global flags (e.g. in tests). Pass None to reset to env-based.
    """
    global _flags
    _flags = flags
