"""GameGrip Safety API — Policy Engine (Phase 3)

Handles policy pack selection, threshold application, and escalation rules.
"""

from typing import Optional, Dict, Any
from config import POLICY_PACKS, PolicyConfig, Decision, AgeBand, Platform
from models import CategoryScore


class PolicyEngine:
    def __init__(self):
        self._packs = POLICY_PACKS.copy()

    def get_policy(self, name: Optional[str]) -> PolicyConfig:
        """Resolve policy pack. Falls back to 'general_community' if not found."""
        if name and name in self._packs:
            return self._packs[name]
        return self._packs["general_community"]

    def list_policies(self) -> Dict[str, Any]:
        """Return all available policy packs with summaries."""
        return {
            name: {
                "name": p.name,
                "description": p.description,
                "thresholds": p.thresholds.model_dump(),
                "log_level": p.log_level,
                "enabled_categories": p.enabled_categories,
            }
            for name, p in self._packs.items()
        }

    def apply_policy(self, base_risk: float, category_scores: list[CategoryScore],
                     policy: PolicyConfig, age_band: AgeBand, platform: Platform) -> tuple[Decision, int, list[str]]:
        """
        Apply policy thresholds, age boosts, platform multipliers, and escalation rules.
        Returns (decision, final_risk, reasons).
        """
        reasons = []

        # 1. Age boost (additive)
        age_boost = policy.age_boosts.get(age_band, 0)
        base_risk += age_boost
        if age_boost > 0:
            reasons.append(f"age_boost({age_band.value}+{age_boost})")

        # 2. Platform multiplier (multiplicative)
        platform_mult = policy.platform_multipliers.get(platform, 1.0)
        final_risk = base_risk * platform_mult
        if platform_mult != 1.0:
            reasons.append(f"platform_mult({platform.value}×{platform_mult})")

        # 3. Escalation rules (category-based overrides)
        for cs in category_scores:
            if cs.score > 0 and cs.category in policy.escalation_rules:
                forced = policy.escalation_rules[cs.category]
                reasons.append(f"escalation({cs.category}→{forced})")
                # If forced to block, we can short-circuit
                if forced == "block":
                    return Decision.BLOCK, min(int(final_risk), 100), reasons
                elif forced == "review":
                    return Decision.REVIEW, min(int(final_risk), 100), reasons

        # 4. Threshold-based decision
        final_risk_int = int(min(final_risk, 100))
        if final_risk_int <= policy.thresholds.allow_max:
            decision = Decision.ALLOW
        elif final_risk_int <= policy.thresholds.warn_max:
            decision = Decision.WARN
        else:
            decision = Decision.BLOCK

        # 5. Auto-review escalation
        if policy.require_review_above and final_risk_int >= policy.require_review_above:
            decision = Decision.REVIEW
            reasons.append(f"auto_review(≥{policy.require_review_above})")

        return decision, final_risk_int, reasons


# Global singleton
policy_engine = PolicyEngine()
