"""
Attention Allocation Receipts

Schemas and utilities for documenting attention allocation decisions.

Key receipts:
- AttentionCertificate: Snapshot of attention state at decision time
- AttentionAllocationReceipt: Full audit trail of who got attention and why
- CaseAttentionProfile: Per-case attention metrics
"""

from dataclasses import dataclass, field, asdict
from typing import Dict, List, Optional, Any
from datetime import datetime
import json
import os

from engine.attention.attention_engine import AttentionRegime


@dataclass
class CaseAttentionProfile:
    """
    Attention metrics for a single case.

    Captures the complete priority calculation:
    Priority = (S_total × Urgency × Neglect) / (Resources × Recourse)
    """
    case_id: str
    priority: float

    # Numerator components
    S_total: float              # Semantic suffering
    urgency: float              # Time sensitivity (0.0-1.0)
    neglect: float              # Waiting time penalty (≥ 1.0)

    # Denominator components
    recourse_exists: bool       # Are there alternative paths?
    recourse_strength: float    # Strength of alternatives (0.0-1.0)

    # Classification
    regime: AttentionRegime     # PREVENTIVE, CRISIS, or SUSTAINED

    # Interventions
    interventions: List[str] = field(default_factory=list)

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dict for JSON serialization"""
        d = asdict(self)
        d["regime"] = self.regime.value  # Enum to string
        return d


@dataclass
class AttentionCertificate:
    """
    Snapshot of attention state at allocation time.

    This is the "measurement" that feeds into allocation decisions.
    Similar to SemanticWeightCertificate but for attention across cohort.
    """
    timestamp: str              # ISO 8601
    domain: str                 # e.g., "prior_authorization"

    # Cohort stats
    total_cases: int
    capacity: int               # How many can we see?
    resource_utilization: float # 0.0-1.0

    # Priority distribution
    mean_priority: float
    max_priority: float

    # Risk profile
    cases_in_crisis: int        # AttentionRegime.CRISIS
    cases_in_sustained: int     # AttentionRegime.SUSTAINED
    cases_without_recourse: int # Trapped, no alternatives

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dict for JSON serialization"""
        return asdict(self)


@dataclass
class AttentionAllocation:
    """
    Result of attention allocation decision.

    Contains:
    - Certificate (snapshot)
    - Seen cases (who gets attention)
    - Waiting cases (who doesn't, must wait)
    - Overflow count
    """
    certificate: AttentionCertificate
    seen: List[CaseAttentionProfile]
    waiting: List[CaseAttentionProfile]
    overflow_count: int

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dict for JSON serialization"""
        return {
            "certificate": self.certificate.to_dict(),
            "seen": [p.to_dict() for p in self.seen],
            "waiting": [p.to_dict() for p in self.waiting],
            "overflow_count": self.overflow_count
        }


@dataclass
class AttentionAllocationReceipt:
    """
    Full audit receipt for attention allocation decision.

    This documents:
    - Who made the allocation decision
    - What was the state of the world (certificate)
    - Who got seen, who didn't
    - What interventions were triggered
    - Fairness metrics
    - Guardian verdict (bias check)

    Stored in .loom/receipts/attention/
    """
    receipt_id: str
    timestamp: str              # ISO 8601
    domain: str

    # Decision metadata
    decision_maker: str         # "attention_engine" or human ID

    # State snapshot
    certificate: AttentionCertificate

    # Allocation results
    seen: List[str]             # Case IDs that got attention
    waiting: List[str]          # Case IDs that must wait

    # Interventions
    interventions_triggered: Dict[str, List[str]]  # case_id -> [intervention, ...]

    # Fairness & accountability
    fairness_metrics: Dict[str, float] = field(default_factory=dict)
    guardian_verdict: str = "APPROVED"  # APPROVED, FLAGGED, DENIED
    guardian_reasoning: List[str] = field(default_factory=list)

    # Audit trail
    receipt_path: Optional[str] = None
    trust_spine_receipt_path: Optional[str] = None
    hash_jcs: Optional[str] = None
    sig_ed25519: Optional[str] = None
    signature_key_id: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dict for JSON serialization"""
        return {
            "receipt_type": "AttentionAllocationReceipt",
            "receipt_id": self.receipt_id,
            "timestamp": self.timestamp,
            "domain": self.domain,
            "decision_maker": self.decision_maker,
            "certificate": self.certificate.to_dict(),
            "seen": self.seen,
            "waiting": self.waiting,
            "interventions_triggered": self.interventions_triggered,
            "fairness_metrics": self.fairness_metrics,
            "guardian_verdict": self.guardian_verdict,
            "guardian_reasoning": self.guardian_reasoning,
            "receipt_path": self.receipt_path,
            "trust_spine_receipt_path": self.trust_spine_receipt_path,
            "hash_jcs": self.hash_jcs,
            "sig_ed25519": self.sig_ed25519,
            "signature_key_id": self.signature_key_id,
        }


def write_attention_allocation_receipt(
    receipt: AttentionAllocationReceipt,
    output_dir: str = ".loom/receipts/attention"
) -> str:
    """
    Write AttentionAllocationReceipt to disk.

    Args:
        receipt: The receipt to write
        output_dir: Directory to write to (default: .loom/receipts/attention)

    Returns:
        str: Path to written receipt
    """
    os.makedirs(output_dir, exist_ok=True)

    # Filename: YYYY-MM-DD_Attention_{receipt_id}.json
    date_str = datetime.utcnow().strftime("%Y-%m-%d")
    filename = f"{date_str}_Attention_{receipt.receipt_id}.json"
    path = os.path.join(output_dir, filename)

    # Update receipt with path
    receipt.receipt_path = path

    # Write JSON
    with open(path, "w") as f:
        json.dump(receipt.to_dict(), f, indent=2)

    return path


def read_attention_allocation_receipt(path: str) -> AttentionAllocationReceipt:
    """
    Read AttentionAllocationReceipt from disk.

    Args:
        path: Path to receipt JSON file

    Returns:
        AttentionAllocationReceipt
    """
    with open(path, "r") as f:
        data = json.load(f)

    # Reconstruct AttentionCertificate
    cert_data = data["certificate"]
    cert = AttentionCertificate(**cert_data)

    # Reconstruct receipt (excluding certificate dict)
    receipt = AttentionAllocationReceipt(
        receipt_id=data["receipt_id"],
        timestamp=data["timestamp"],
        domain=data["domain"],
        decision_maker=data["decision_maker"],
        certificate=cert,
        seen=data["seen"],
        waiting=data["waiting"],
        interventions_triggered=data["interventions_triggered"],
        fairness_metrics=data.get("fairness_metrics", {}),
        guardian_verdict=data.get("guardian_verdict", "APPROVED"),
        guardian_reasoning=data.get("guardian_reasoning", []),
        receipt_path=data.get("receipt_path"),
        trust_spine_receipt_path=data.get("trust_spine_receipt_path"),
        hash_jcs=data.get("hash_jcs"),
        sig_ed25519=data.get("sig_ed25519"),
        signature_key_id=data.get("signature_key_id"),
    )

    return receipt


# Example helper: Create receipt from allocation
def create_receipt_from_allocation(
    allocation: AttentionAllocation,
    domain: str,
    decision_maker: str = "attention_engine"
) -> AttentionAllocationReceipt:
    """
    Create AttentionAllocationReceipt from AttentionAllocation.

    Args:
        allocation: The allocation result
        domain: Domain name (e.g., "prior_authorization")
        decision_maker: Who made the decision

    Returns:
        AttentionAllocationReceipt ready to be written
    """
    receipt_id = f"ATN-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"

    # Collect interventions
    interventions_triggered = {
        p.case_id: p.interventions
        for p in allocation.seen
        if p.interventions
    }

    # Compute fairness metrics
    total_cases = allocation.certificate.total_cases
    overflow_rate = allocation.overflow_count / total_cases if total_cases > 0 else 0.0

    crisis_and_sustained = allocation.certificate.cases_in_crisis + allocation.certificate.cases_in_sustained
    crisis_seen = len([p for p in allocation.seen if p.regime in (AttentionRegime.CRISIS, AttentionRegime.SUSTAINED)])
    crisis_coverage = crisis_seen / max(crisis_and_sustained, 1)

    fairness_metrics = {
        "capacity_utilization": allocation.certificate.resource_utilization,
        "overflow_rate": overflow_rate,
        "crisis_coverage": crisis_coverage,
        "recourse_gap": allocation.certificate.cases_without_recourse / max(total_cases, 1)
    }

    receipt = AttentionAllocationReceipt(
        receipt_id=receipt_id,
        timestamp=datetime.utcnow().isoformat() + "Z",
        domain=domain,
        decision_maker=decision_maker,
        certificate=allocation.certificate,
        seen=[p.case_id for p in allocation.seen],
        waiting=[p.case_id for p in allocation.waiting],
        interventions_triggered=interventions_triggered,
        fairness_metrics=fairness_metrics,
        guardian_verdict="APPROVED",  # Would integrate with Guardian
        guardian_reasoning=[]
    )

    return receipt
