"""
CouncilReceipt schema for council deliberation auditing.

This receipt captures:
- The question/intent posed to the council
- Expert perspectives gathered
- Disagreement metrics
- Final synthesis

Integrates with Guardian for gating high-disagreement outputs.
"""

from __future__ import annotations

from datetime import datetime
from typing import Any, Dict, List, Literal, Optional
import uuid

from receipts.base import BaseReceipt


class CouncilPerspectiveRecord:
    """Serializable record of a single expert perspective."""

    def __init__(
        self,
        role: str,
        capability: str,
        model_id: Optional[str],
        content_summary: str,
        score: Optional[float],
        latency_ms: float,
    ):
        self.role = role
        self.capability = capability
        self.model_id = model_id
        self.content_summary = content_summary
        self.score = score
        self.latency_ms = latency_ms

    def to_dict(self) -> Dict[str, Any]:
        return {
            "role": self.role,
            "capability": self.capability,
            "model_id": self.model_id,
            "content_summary": self.content_summary,
            "score": self.score,
            "latency_ms": self.latency_ms,
        }

    @classmethod
    def from_dict(cls, d: Dict[str, Any]) -> "CouncilPerspectiveRecord":
        return cls(
            role=d["role"],
            capability=d["capability"],
            model_id=d.get("model_id"),
            content_summary=d["content_summary"],
            score=d.get("score"),
            latency_ms=d.get("latency_ms", 0.0),
        )


class CouncilReceipt(BaseReceipt):
    """
    Receipt for council deliberation.

    Captures:
    - Intent/question posed
    - Expert count and perspectives
    - Disagreement metrics (std, range)
    - Synthesis output
    - Guardian gating outcome

    Example usage:
        receipt = CouncilReceipt(
            question="Should we approve PA request X?",
            context_hash="sha256:abc...",
            expert_count=4,
            disagreement_score=0.23,
            disagreement_range=0.5,
            high_disagreement=False,
            synthesis="Council recommends approval with conditions.",
            perspectives=[...],
        )
    """

    receipt_type: Literal["CouncilReceipt"] = "CouncilReceipt"

    # Input
    question: str
    context_hash: Optional[str] = None  # Hash of context for auditability

    # Expert perspectives
    expert_count: int
    perspectives: List[Dict[str, Any]]  # List of CouncilPerspectiveRecord.to_dict()

    # Disagreement metrics
    disagreement_score: float  # council_std from evaluate_council_disagreement
    disagreement_range: float  # council_range
    high_disagreement: bool

    # Output
    synthesis: str
    synthesis_truncated: bool = False  # True if synthesis was truncated for storage

    # Timing
    total_latency_ms: float = 0.0

    # Links
    parent_receipt_id: Optional[str] = None  # Parent decision receipt if nested
    guardian_outcome: Optional[str] = None  # "allow", "escalate", "deny"

    def __init__(
        self,
        question: str,
        expert_count: int,
        disagreement_score: float,
        disagreement_range: float,
        high_disagreement: bool,
        synthesis: str,
        perspectives: Optional[List[Dict[str, Any]]] = None,
        context_hash: Optional[str] = None,
        total_latency_ms: float = 0.0,
        parent_receipt_id: Optional[str] = None,
        guardian_outcome: Optional[str] = None,
        receipt_id: Optional[str] = None,
        **kwargs,
    ):
        super().__init__(
            receipt_id=receipt_id or f"COUNCIL-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}-{uuid.uuid4().hex[:8]}",
            **kwargs,
        )
        self.question = question
        self.context_hash = context_hash
        self.expert_count = expert_count
        self.perspectives = perspectives or []
        self.disagreement_score = disagreement_score
        self.disagreement_range = disagreement_range
        self.high_disagreement = high_disagreement
        self.synthesis = synthesis
        self.synthesis_truncated = len(synthesis) > 2000
        self.total_latency_ms = total_latency_ms
        self.parent_receipt_id = parent_receipt_id
        self.guardian_outcome = guardian_outcome

    def to_dict(self) -> Dict[str, Any]:
        """Serialize to dictionary for storage."""
        base = super().to_dict() if hasattr(super(), "to_dict") else {}
        base.update({
            "receipt_type": self.receipt_type,
            "receipt_id": self.receipt_id,
            "question": self.question,
            "context_hash": self.context_hash,
            "expert_count": self.expert_count,
            "perspectives": self.perspectives,
            "disagreement_score": self.disagreement_score,
            "disagreement_range": self.disagreement_range,
            "high_disagreement": self.high_disagreement,
            "synthesis": self.synthesis[:2000] if len(self.synthesis) > 2000 else self.synthesis,
            "synthesis_truncated": self.synthesis_truncated,
            "total_latency_ms": self.total_latency_ms,
            "parent_receipt_id": self.parent_receipt_id,
            "guardian_outcome": self.guardian_outcome,
            "timestamp": datetime.utcnow().isoformat(),
        })
        return base

    def guardian_input(self) -> Dict[str, Any]:
        """
        Return dict suitable for Guardian/OPA policy evaluation.

        Use with guardian/policies/council_synthesis.rego
        """
        return {
            "expert_count": self.expert_count,
            "disagreement_score": self.disagreement_score,
            "disagreement_range": self.disagreement_range,
            "high_disagreement": self.high_disagreement,
            "synthesis_length": len(self.synthesis),
        }


def from_deliberation(deliberation, question: str, context_hash: Optional[str] = None) -> CouncilReceipt:
    """
    Factory to create CouncilReceipt from CouncilDeliberation.

    Args:
        deliberation: CouncilDeliberation instance from CouncilRouter.convene()
        question: Original question posed
        context_hash: Optional hash of context

    Returns:
        CouncilReceipt ready for storage/Guardian evaluation
    """
    perspectives = []
    for p in deliberation.perspectives:
        perspectives.append({
            "role": p.role,
            "capability": p.capability,
            "model_id": p.model_id,
            "content_summary": p.content[:200] if len(p.content) > 200 else p.content,
            "score": p.meta.get("score"),
            "latency_ms": p.latency_ms,
        })

    return CouncilReceipt(
        question=question,
        context_hash=context_hash,
        expert_count=deliberation.council_size,
        perspectives=perspectives,
        disagreement_score=deliberation.council_std,
        disagreement_range=deliberation.council_range,
        high_disagreement=deliberation.high_disagreement,
        synthesis=deliberation.synthesis,
        total_latency_ms=deliberation.latency_ms,
    )
