from __future__ import annotations

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

from pydantic import Field

from receipts.base import BaseReceipt


class VoiceIncidentReceipt(BaseReceipt):
    """
    Emitted by the Voice Sentinel organ when it detects a runtime voice incident
    (loops, overlaps, VAD glitches, etc.).
    """

    receipt_type: Literal["VoiceIncidentReceipt"] = Field(default="VoiceIncidentReceipt")
    domain: Literal["runtime"] = Field(default="runtime")
    organ: Literal["voice_sentinel"] = Field(default="voice_sentinel")
    receipt_id: str = Field(default_factory=lambda: f"VI_{uuid.uuid4().hex}")

    # What went wrong?
    incident_type: str = Field(
        ...,
        description="Class of incident: 'loop' | 'overlap' | 'vad_glitch' | 'other'.",
    )
    severity: float = Field(
        ...,
        ge=0.0,
        le=1.0,
        description="Rough severity score (0.0–1.0).",
    )

    # Evidence window
    text_stubs: List[str] = Field(
        default_factory=list,
        description="Repeated phrase prefixes or stubs (e.g., ['I’m really', 'I’m really']).",
    )
    duration_ms: int = Field(
        default=0,
        description="Approximate duration of the incident window in milliseconds.",
    )
    events_window: Dict[str, Any] = Field(
        default_factory=dict,
        description="Compact summary of recent VAD/TTS/ASR/UI events.",
    )

    # What the sentinel actually did
    action_taken: str = Field(
        default="none",
        description="Action: 'switch_to_text' | 'muted_mic' | 'none' | 'alerted_user'.",
    )

    # Context (app, mode, meeting, etc.)
    context: Dict[str, Any] = Field(
        default_factory=dict,
        description="Extra context: app, window title, conversation id, meeting id, etc.",
    )
    intent_hash: Optional[str] = Field(
        default=None,
        description="Hash or identifier for the utterance intent (used for loop detection).",
    )
    veto_reason: Optional[str] = Field(
        default=None,
        description="Optional veto rationale when incident_type='veto'.",
    )
    crif: Optional[Dict[str, float]] = Field(
        default=None,
        description="Optional CRIF signature: {'C','R','I','F'} in [0,1].",
    )
