"""
Proof policy matrix loader and helpers.

Single source of truth for mapping (environment, action_class) -> required trust tier.
Guardian, Sediment, and learning_tier computation should all rely on this module to
avoid drift.
"""

from __future__ import annotations

import functools
from pathlib import Path
from typing import Dict, List

import yaml


class ProofPolicyMatrix:
    """Utility for accessing the proof policy matrix YAML."""

    def __init__(self, matrix: Dict[str, Dict[str, str]], tiers: List[str]):
        self._matrix = matrix
        self._tiers = tiers
        self._tier_index = {name: idx for idx, name in enumerate(tiers)}

    @classmethod
    def load_default(cls) -> "ProofPolicyMatrix":
        """Load the default matrix from docs/schemas/proof_policy_matrix.yaml."""
        path = (
            Path(__file__)
            .resolve()
            .parent.parent
            / "docs"
            / "schemas"
            / "proof_policy_matrix.yaml"
        )
        if not path.exists():
            raise FileNotFoundError(f"Proof policy matrix not found at {path}")
        data = yaml.safe_load(path.read_text())
        matrix = data.get("matrix", {})
        tiers = data.get("tiers", [])
        if not tiers:
            raise ValueError("tiers must be defined in proof_policy_matrix.yaml")
        return cls(matrix=matrix, tiers=tiers)

    def required_tier(self, environment: str, action_class: str) -> str:
        """Return required tier for (env, action_class)."""
        env_matrix = self._matrix.get(environment)
        if not env_matrix:
            raise KeyError(f"Unknown environment in proof policy matrix: {environment}")
        required = env_matrix.get(action_class)
        if not required:
            raise KeyError(
                f"Unknown action_class '{action_class}' for environment '{environment}'"
            )
        return required

    def tier_at_least(self, actual: str, required: str) -> bool:
        """Return True if actual tier is >= required tier based on ordering."""
        if actual not in self._tier_index:
            raise KeyError(f"Unknown tier: {actual}")
        if required not in self._tier_index:
            raise KeyError(f"Unknown tier: {required}")
        return self._tier_index[actual] >= self._tier_index[required]


@functools.lru_cache(maxsize=1)
def default_matrix() -> ProofPolicyMatrix:
    """Cached accessor for the default matrix."""
    return ProofPolicyMatrix.load_default()

