"""
Guardian Receipt Schemas

Guardian review, veto, approval, and evaluation receipts for constitutional oversight.
"""

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

from pydantic import Field

from receipts.base import BaseReceipt


class GuardianEvaluationReceipt(BaseReceipt):
    """
    Receipt emitted for every guardian constitutional evaluation.

    This is the canonical record of a guardian's constitutional check result,
    emitted for both ALLOW and DENY decisions. It captures all 5 constitutional
    checks (pattern blocking, dignity, MVL standoff, constitutional preflight,
    risk-level) plus perception guard for screen-bound actions.

    Use GuardianVetoReceipt for detailed veto tracking with appeals.
    Use GuardianApprovalReceipt for explicit approvals requiring oversight.
    """

    receipt_type: str = Field(default="guardian_evaluation")

    # Core identifiers
    envelope_id: str = Field(..., description="ID of the decision envelope being evaluated")
    verdict_id: str = Field(..., description="Unique ID for this guardian evaluation")

    # Decision outcome
    decision: Literal["ALLOW", "DENY", "CONFIRM_REQUIRED", "THROTTLE"] = Field(
        ..., description="Guardian decision outcome"
    )
    reasoning: str = Field(default="", description="Human-readable reasoning")

    # Constitutional checks (5 checks + optional perception guard)
    checks: Dict[str, Any] = Field(
        default_factory=dict,
        description="Results of each constitutional check (pattern_block, dignity, mvl_standoff, constitutional, risk_level, perception_guard)"
    )

    # Aggregated violations/denials
    forbids: List[str] = Field(default_factory=list, description="Forbidden operations detected")
    deny_reasons: List[str] = Field(default_factory=list, description="Reasons for denial")

    # Dignity metrics
    dignity_score: float = Field(default=0.5, ge=0.0, le=1.0, description="Computed dignity score")
    passes_dignity_floor: bool = Field(default=True, description="Whether dignity floor (0.15) passed")

    # MVL Standoff (prophecy-guided strictness)
    mvl_triggered: bool = Field(default=False, description="Whether MVL standoff was triggered")
    prophecy_id: Optional[str] = Field(default=None, description="Prophecy ID if MVL triggered")
    prophecy_risk_level: Optional[str] = Field(default=None, description="Risk level from prophecy")

    # Constitutional violations
    constitutional_violations: List[str] = Field(
        default_factory=list, description="Specific constitutional violations detected"
    )
    floor_passed: bool = Field(default=True, description="Whether constitutional floor passed")

    # Risk-level gating
    risk_level: str = Field(default="UNKNOWN", description="Overall risk level (SAFE/CAUTION/DANGER/CRITICAL)")
    thermal_concern: bool = Field(default=False, description="Whether thermal/system health concern")
    execution_mode: str = Field(default="live", description="Execution mode (live/ghost/confirm_per_action)")

    # Genesis coherence (optional)
    delta_c: Optional[float] = Field(default=None, description="Genesis coherence score")
    delta_c_status: Optional[str] = Field(default=None, description="ΔC status string")

    # Perception guard (for screen/vision-bound actions)
    perception_guard_passed: bool = Field(default=True, description="Whether perception guard passed")
    perception_guard_reason: Optional[str] = Field(default=None, description="Reason for perception guard result")
    perception_guard_status: Optional[str] = Field(default=None, description="PerceptionGateStatus value")
    perception_age_sec: Optional[float] = Field(default=None, description="Age of perception data in seconds")

    @classmethod
    def from_expanded(
        cls,
        expanded: Any,
        domain: str = "governance",
        parent_ids: Optional[List[str]] = None,
    ) -> "GuardianEvaluationReceipt":
        """
        Create a GuardianEvaluationReceipt from a GuardianReceiptExpanded dataclass.

        Args:
            expanded: GuardianReceiptExpanded instance
            domain: Receipt domain
            parent_ids: Parent receipt IDs for lineage

        Returns:
            GuardianEvaluationReceipt ready for persistence
        """
        # Convert checks dict (CheckResult -> dict)
        checks_dict = {}
        for name, check in getattr(expanded, "checks", {}).items():
            if hasattr(check, "to_dict"):
                checks_dict[name] = check.to_dict()
            elif isinstance(check, dict):
                checks_dict[name] = check
            else:
                checks_dict[name] = {"passed": getattr(check, "passed", True)}

        # Get decision string
        decision_val = expanded.decision
        if hasattr(decision_val, "value"):
            decision_str = decision_val.value
        else:
            decision_str = str(decision_val)

        # Get risk level string
        risk_val = getattr(expanded, "risk_level", "UNKNOWN")
        if hasattr(risk_val, "value"):
            risk_str = risk_val.value
        else:
            risk_str = str(risk_val)

        # Get prophecy risk level string
        prophecy_risk = getattr(expanded, "prophecy_risk_level", None)
        if prophecy_risk is not None and hasattr(prophecy_risk, "value"):
            prophecy_risk = prophecy_risk.value

        return cls(
            receipt_id=expanded.receipt_id,
            domain=domain,
            envelope_id=getattr(expanded, "envelope_id", ""),
            verdict_id=expanded.verdict_id,
            decision=decision_str,
            reasoning=getattr(expanded, "reasoning", ""),
            checks=checks_dict,
            forbids=list(getattr(expanded, "forbids", [])),
            deny_reasons=list(getattr(expanded, "deny_reasons", [])),
            dignity_score=getattr(expanded, "dignity_score", 0.5),
            passes_dignity_floor=getattr(expanded, "passes_dignity_floor", True),
            mvl_triggered=getattr(expanded, "mvl_triggered", False),
            prophecy_id=getattr(expanded, "prophecy_id", None),
            prophecy_risk_level=prophecy_risk,
            constitutional_violations=list(getattr(expanded, "constitutional_violations", [])),
            floor_passed=getattr(expanded, "floor_passed", True),
            risk_level=risk_str,
            thermal_concern=getattr(expanded, "thermal_concern", False),
            execution_mode=getattr(expanded, "execution_mode", "live"),
            delta_c=getattr(expanded, "delta_c", None),
            delta_c_status=getattr(expanded, "delta_c_status", None),
            perception_guard_passed=getattr(expanded, "perception_guard_passed", True),
            perception_guard_reason=getattr(expanded, "perception_guard_reason", None),
            perception_guard_status=getattr(expanded, "perception_guard_status", None),
            perception_age_sec=getattr(expanded, "perception_age_sec", None),
            parent_ids=parent_ids or [],
        )


class GuardianVetoReceipt(BaseReceipt):
    """
    Receipt emitted when guardian vetoes an action for constitutional reasons.

    Guardians can veto actions that:
    - Violate dignity floor (< 0.15)
    - Fail SIGIL checks (Identity/Scope/Dignity/Replay)
    - Risk PHI leakage
    - Violate other constitutional principles

    Vetoes include repair paths when possible.
    """

    receipt_type: str = Field(default="guardian_veto")

    # Veto details
    guardian: str = Field(..., description="Guardian who issued veto")
    action_id: str = Field(..., description="ID of vetoed action")
    action_type: str = Field(..., description="Type of action (pr_merge, deployment, etc.)")

    # Veto reason
    veto_reason: str = Field(..., description="Primary constitutional violation")
    veto_category: str = Field(
        ...,
        description="DIGNITY_FLOOR | SIGIL_FAILURE | PHI_RISK | OTHER"
    )

    # Evidence
    violation_details: Dict[str, Any] = Field(
        ..., description="Specific details of the violation"
    )

    # Repair guidance
    repair_required: bool = Field(
        default=True, description="Can this be repaired and retried?"
    )
    repair_suggestions: List[str] = Field(
        default_factory=list,
        description="Specific steps to repair the violation"
    )

    # Resolution tracking
    appeal_allowed: bool = Field(
        default=True, description="Can this veto be appealed?"
    )
    appealed: bool = Field(default=False, description="Has this been appealed?")
    appeal_decision: Optional[str] = Field(
        None, description="Decision on appeal (UPHELD | OVERTURNED)"
    )
    appeal_guardian: Optional[str] = Field(
        None, description="Guardian who reviewed appeal"
    )


class GuardianApprovalReceipt(BaseReceipt):
    """
    Receipt emitted when guardian approves an action that required oversight.

    Some actions require guardian approval even if they pass automated checks:
    - PHI handling operations
    - Dignity floor exceptions (0.10-0.15 range with justification)
    - Major architectural changes
    - Constitutional amendments
    """

    receipt_type: str = Field(default="guardian_approval")

    # Approval details
    guardian: str = Field(..., description="Guardian who issued approval")
    action_id: str = Field(..., description="ID of approved action")
    action_type: str = Field(..., description="Type of action")

    # Review details
    approval_category: str = Field(
        ...,
        description="PHI_HANDLING | FLOOR_EXCEPTION | ARCHITECTURE | CONSTITUTIONAL"
    )
    review_notes: str = Field(..., description="Guardian's review notes")

    # Conditions
    conditional: bool = Field(
        default=False, description="Approval has conditions"
    )
    conditions: List[str] = Field(
        default_factory=list,
        description="Conditions that must be met"
    )

    # Monitoring
    requires_followup: bool = Field(
        default=False, description="Requires post-action review"
    )
    followup_date: Optional[str] = Field(
        None, description="ISO date for followup review"
    )


class GuardianReviewReceipt(BaseReceipt):
    """
    Receipt emitted for periodic guardian reviews of system health.

    Guardians conduct regular reviews of:
    - Dignity floor violations (resolved and unresolved)
    - EVHD correlation trends
    - Receipt integrity
    - Constitutional compliance
    """

    receipt_type: str = Field(default="guardian_review")

    # Review details
    guardian: str = Field(..., description="Guardian conducting review")
    review_type: str = Field(
        ...,
        description="WEEKLY | MONTHLY | INCIDENT | CONSTITUTIONAL"
    )
    review_period_start: str = Field(..., description="Start of review period (ISO)")
    review_period_end: str = Field(..., description="End of review period (ISO)")

    # Findings
    findings: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="List of findings (issue, severity, recommendation)"
    )

    # Summary
    overall_status: str = Field(
        ...,
        description="HEALTHY | CONCERNING | CRITICAL"
    )
    summary: str = Field(..., description="Guardian's summary of review")

    # Actions required
    actions_required: List[str] = Field(
        default_factory=list,
        description="Actions that must be taken"
    )

    # Next review
    next_review_date: Optional[str] = Field(
        None, description="ISO date for next scheduled review"
    )
