"""In-memory TTL cache for expensive scoring and metrics calculations.

The cache is a simple dict with timestamps. It is invalidated when tests
are validated, scores change, or an explicit ``invalidate`` call is made.

Thread-safe: each worker process has its own dict, and the TTL ensures
stale data does not persist longer than ``CACHE_TTL`` seconds.
"""

import time
from typing import Any, Optional

CACHE_TTL = 300  # 5 minutes

_cache: dict[str, dict[str, Any]] = {}


def get(key: str) -> Optional[Any]:
    """Return cached value if present and not expired, else None."""
    entry = _cache.get(key)
    if entry is None:
        return None
    if time.time() - entry["ts"] > CACHE_TTL:
        _cache.pop(key, None)
        return None
    return entry["data"]


def put(key: str, data: Any) -> None:
    """Store *data* under *key* with the current timestamp."""
    _cache[key] = {"data": data, "ts": time.time()}


def invalidate(key: Optional[str] = None) -> None:
    """Remove one key or clear the whole cache."""
    if key is None:
        _cache.clear()
    else:
        _cache.pop(key, None)


# ── High-level helpers ────────────────────────────────────────────────


def get_organization_score_cached(db):
    """Cached wrapper around ``calculate_organization_score``."""
    from app.services.scoring_service import calculate_organization_score

    cached = get("org_score")
    if cached is not None:
        return cached

    result = calculate_organization_score(db)
    put("org_score", result)
    return result


def get_operational_metrics_cached(db):
    """Cached wrapper around operational metrics (MTTD, MTTR, efficacy)."""
    from app.services.operational_metrics_service import (
        calculate_mttd,
        calculate_mttr,
        calculate_detection_efficacy,
        calculate_alert_fidelity,
        calculate_coverage_velocity,
        calculate_validation_throughput,
        calculate_rejection_rate,
    )

    cached = get("op_metrics")
    if cached is not None:
        return cached

    result = {
        "mttd": calculate_mttd(db),
        "mttr": calculate_mttr(db),
        "detection_efficacy": calculate_detection_efficacy(db),
        "alert_fidelity": calculate_alert_fidelity(db),
        "coverage_velocity": calculate_coverage_velocity(db),
        "validation_throughput": calculate_validation_throughput(db),
        "rejection_rate": calculate_rejection_rate(db),
    }
    put("op_metrics", result)
    return result
