"""
Kernel Receipt Types for the 270M Always-On Conductor

These receipts document routing decisions, safety checks, and escalations
made by the always-on kernel model. Every decision is auditable, replayable,
and Kairos-stamped.

Receipt Types:
- KernelRoutingReceipt: Documents tier routing decisions (kernel/local/cloud)
- SafetyCheckReceipt: Documents ALLOW/DENY/ESCALATE decisions from micro-filters
- EscalationReceipt: Documents why a request was escalated to a higher tier

See: docs/architecture/KERNEL_SPEC.md (to be created)
"""

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Literal, Optional, TYPE_CHECKING

from receipts.base import BaseReceipt, Domain
from receipts.compat.pyd import Field

if TYPE_CHECKING:
    from src.organs.kairos_engine import KairosStamp


# === Enums ===

class RoutingTier(str, Enum):
    """Which tier handles the request."""
    KERNEL = "kernel"           # Handle locally with 270M kernel
    LOCAL_SPECIALIST = "local"  # Wake a 0.5-3B specialist
    CLOUD = "cloud"             # Escalate to cloud heavyweight
    GUARDIAN = "guardian"       # Escalate for safety/dignity review


class SafetyVerdict(str, Enum):
    """Safety check outcome."""
    ALLOW = "allow"       # Safe to proceed
    DENY = "deny"         # Block the action
    ESCALATE = "escalate" # Needs human or higher-tier review
    ASK = "ask"           # Request clarification


class EscalationReason(str, Enum):
    """Why we escalated to a higher tier."""
    TOO_HARD = "too_hard"           # Complexity exceeds kernel capability
    LONG_CONTEXT = "long_context"   # Context too long for kernel
    NEW_DOMAIN = "new_domain"       # Unknown domain, needs specialist
    SAFETY_RISK = "safety_risk"     # Potential harm, needs review
    USER_REQUEST = "user_request"   # User explicitly requested max power
    TIMEOUT = "timeout"             # Lower tier timed out
    LOW_CONFIDENCE = "low_confidence"  # Kernel unsure about decision


# === Receipt Types ===

class KernelRoutingReceipt(BaseReceipt):
    """
    Documents a routing decision made by the 270M kernel.
    
    Emitted every time the kernel decides which tier handles a request.
    This is the primary audit trail for the tiered model architecture.
    
    Fields:
        task_id: Unique identifier for the task/request
        intent_summary: Short summary of user intent (for debugging)
        
        decision: Which tier was selected
        model_used: Specific model ID that will handle the request
        tool_calls: List of tools/agents to invoke
        
        budget_tier: Latency/cost/risk budget (low/medium/high)
        latency_ms: Time to make the routing decision
        
        guards: Safety flags (requires_confirmation, dry_run_only, risky)
        plan_steps: 1-3 step plan sketch
        
        kairos: Kairos stamp at decision time
    """
    receipt_type: str = "KernelRoutingReceipt"
    
    # Task identification
    task_id: str = Field(description="Unique task/request identifier")
    intent_summary: str = Field(description="Short summary of user intent")
    
    # Routing decision
    decision: RoutingTier = Field(description="Which tier handles this request")
    model_used: str = Field(description="Specific model ID (e.g., 'kernel-270m-v1', 'claude-3-opus')")
    tool_calls: List[Dict[str, Any]] = Field(
        default_factory=list, 
        description="Tools/agents to invoke [{tool: str, args: dict}]"
    )
    
    # Budget and performance
    budget_tier: Literal["low", "medium", "high"] = Field(
        default="medium",
        description="Latency/cost/risk budget tier"
    )
    latency_ms: float = Field(description="Time to make routing decision in milliseconds")
    tokens_used: int = Field(default=0, description="Tokens consumed for this decision")
    
    # Safety and guards
    guards: Dict[str, bool] = Field(
        default_factory=lambda: {
            "requires_confirmation": False,
            "dry_run_only": False,
            "risky": False,
        },
        description="Safety flags for downstream handlers"
    )
    
    # Plan sketch
    plan_steps: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="1-3 step plan [{step: int, tool: str, args: dict, description: str}]"
    )
    
    # State context
    state_hash_pre: Optional[str] = Field(
        default=None, 
        description="Hash of state before routing decision"
    )
    
    # Kairos temporal stamp
    kairos: Optional["KairosStamp"] = Field(
        default=None,
        description="Kairos stamp at decision time"
    )
    
    # Domain
    domain: str = Field(default=Domain.GOVERNANCE.value)


class SafetyCheckReceipt(BaseReceipt):
    """
    Documents a safety check performed by micro-filters (Tier 0).
    
    These are fast pre-filters that run BEFORE the kernel or Guardian.
    They catch obvious dangers without waking heavyweight safety systems.
    
    Fields:
        check_type: What kind of check (secret_scan, url_allowlist, command_filter, etc.)
        input_hash: Hash of the input being checked (for replay)
        
        verdict: ALLOW/DENY/ESCALATE/ASK
        reason: Why this verdict was reached
        
        confidence: Confidence in the verdict [0.0, 1.0]
        latency_us: Time in microseconds (these should be <1ms)
        
        escalate_to: If ESCALATE, which component should review
    """
    receipt_type: str = "SafetyCheckReceipt"
    
    # Check identification
    check_type: str = Field(description="Type of safety check performed")
    input_hash: str = Field(description="SHA256 hash of input for replay")
    
    # Verdict
    verdict: SafetyVerdict = Field(description="Safety check outcome")
    reason: str = Field(description="Human-readable reason for verdict")
    
    # Confidence and performance
    confidence: float = Field(
        ge=0.0, le=1.0,
        description="Confidence in verdict [0.0, 1.0]"
    )
    latency_us: float = Field(description="Check latency in microseconds")
    
    # Escalation
    escalate_to: Optional[str] = Field(
        default=None,
        description="Component to escalate to (e.g., 'guardian', 'human', 'kernel')"
    )
    
    # Context
    triggered_rules: List[str] = Field(
        default_factory=list,
        description="Which rules/patterns triggered this verdict"
    )
    
    # Kairos temporal stamp
    kairos: Optional["KairosStamp"] = Field(
        default=None,
        description="Kairos stamp at check time"
    )
    
    # Domain
    domain: str = Field(default=Domain.GOVERNANCE.value)


class EscalationReceipt(BaseReceipt):
    """
    Documents an escalation from one tier to another.
    
    Emitted when:
    - Kernel escalates to local specialist
    - Kernel or specialist escalates to cloud
    - Any tier escalates to human review
    
    This creates an audit trail for why expensive resources were used.
    
    Fields:
        task_id: Task being escalated
        from_tier: Tier that decided to escalate
        to_tier: Tier receiving the escalation
        
        reason: Why escalation was necessary
        reason_details: Additional context
        
        context_summary: Compressed context passed to higher tier
        budget_impact: Cost/latency impact estimate
    """
    receipt_type: str = "EscalationReceipt"
    
    # Task identification
    task_id: str = Field(description="Task being escalated")
    
    # Escalation path
    from_tier: RoutingTier = Field(description="Tier that decided to escalate")
    to_tier: RoutingTier = Field(description="Tier receiving the escalation")
    from_model: str = Field(description="Model ID that made escalation decision")
    to_model: Optional[str] = Field(
        default=None,
        description="Model ID that will handle (if known)"
    )
    
    # Reason
    reason: EscalationReason = Field(description="Why escalation was necessary")
    reason_details: str = Field(
        default="",
        description="Additional context for the escalation"
    )
    
    # Context handoff
    context_summary: str = Field(
        default="",
        description="Compressed context passed to higher tier"
    )
    context_tokens: int = Field(
        default=0,
        description="Token count of context summary"
    )
    
    # Budget impact
    budget_impact: Dict[str, Any] = Field(
        default_factory=lambda: {
            "estimated_cost_usd": 0.0,
            "estimated_latency_ms": 0,
            "priority": "normal",
        },
        description="Estimated cost/latency impact"
    )
    
    # Performance metrics from escalating tier
    escalating_tier_latency_ms: float = Field(
        default=0.0,
        description="How long the escalating tier tried before giving up"
    )
    escalating_tier_tokens: int = Field(
        default=0,
        description="Tokens consumed by escalating tier"
    )
    
    # Kairos temporal stamp
    kairos: Optional["KairosStamp"] = Field(
        default=None,
        description="Kairos stamp at escalation time"
    )
    
    # Kairos cycle info for routing decisions
    cycles_at_escalation: Optional[int] = Field(
        default=None,
        description="Kairos cycle count when escalation occurred"
    )
    
    # Guardian decision fields (when to_tier=GUARDIAN)
    guardian_decision: Optional[str] = Field(
        default=None,
        description="Guardian's decision: allow/warn/refuse/hold"
    )
    guardian_approved: Optional[bool] = Field(
        default=None,
        description="Whether Guardian approved the request"
    )
    
    # Dignity floor linkage (for floor violations)
    floor_receipt_id: Optional[str] = Field(
        default=None,
        description="Receipt ID of the floor check that triggered escalation"
    )
    measured_dignity: Optional[float] = Field(
        default=None,
        description="Measured dignity score that triggered escalation"
    )
    
    # Domain
    domain: str = Field(default=Domain.GOVERNANCE.value)


# === Rebuild models for forward references ===

def _rebuild_kernel_models():
    """Rebuild Pydantic models to resolve KairosStamp forward reference."""
    try:
        from src.organs.kairos_engine import KairosStamp
        KernelRoutingReceipt.model_rebuild()
        SafetyCheckReceipt.model_rebuild()
        EscalationReceipt.model_rebuild()
    except ImportError:
        pass  # KairosStamp may not be available in all contexts


_rebuild_kernel_models()
