"""Canonical event/state contracts for the AI calling platform.

Stdlib-only (dataclasses + enums) so every service — and tooling — can import
it without dependency baggage. The Django side consumes these shapes as plain
JSON through the three signed callbacks; browsers receive them via
websocket_service.

Keep in sync with docs/ai-calling-platform/PHASE1-ARCHITECTURE.md §6/§8.
"""

from dataclasses import dataclass, field, asdict
from enum import Enum
from typing import Optional


class CallState(str, Enum):
    QUEUED = "QUEUED"
    RINGING = "RINGING"
    CONNECTED = "CONNECTED"
    INTRODUCTION = "INTRODUCTION"
    QUESTIONING = "QUESTIONING"
    FOLLOW_UP = "FOLLOW_UP"
    SUMMARIZATION = "SUMMARIZATION"
    COMPLETED = "COMPLETED"
    # error states
    FAILED = "FAILED"
    BUSY = "BUSY"
    NO_ANSWER = "NO_ANSWER"
    DROPPED = "DROPPED"


TERMINAL_STATES = {CallState.COMPLETED, CallState.FAILED, CallState.BUSY,
                   CallState.NO_ANSWER, CallState.DROPPED}

# How platform states map onto the ATS AICall.Status values
ATS_STATUS_MAP = {
    CallState.QUEUED: "queued",
    CallState.RINGING: "dialing",
    CallState.CONNECTED: "in_progress",
    CallState.INTRODUCTION: "in_progress",
    CallState.QUESTIONING: "in_progress",
    CallState.FOLLOW_UP: "in_progress",
    CallState.SUMMARIZATION: "in_progress",
    CallState.COMPLETED: "completed",
    CallState.FAILED: "failed",
    CallState.BUSY: "busy",
    CallState.NO_ANSWER: "no_answer",
    CallState.DROPPED: "failed",
}


class BrowserEvent(str, Enum):
    """Event names fanned out to the ATS UI by websocket_service."""
    CALL_QUEUED = "call_queued"
    CALL_STARTED = "call_started"
    CALL_CONNECTED = "call_connected"
    TRANSCRIPT_UPDATED = "transcript_updated"
    QUESTION_ASKED = "question_asked"
    CALL_COMPLETED = "call_completed"
    REPORT_GENERATED = "report_generated"
    CALL_FAILED = "call_failed"


@dataclass
class Utterance:
    sequence: int
    speaker: str                      # AGENT | CANDIDATE
    message: str
    started_ms: Optional[int] = None
    ended_ms: Optional[int] = None
    language: str = "en"              # en | hi
    interrupted: bool = False

    def to_dict(self):
        return asdict(self)


@dataclass
class Evaluation:
    technical_score: Optional[int] = None
    communication_score: Optional[int] = None
    experience_score: Optional[int] = None
    confidence_score: Optional[int] = None
    overall_score: Optional[int] = None
    classification: str = ""          # Strong Match | Potential Match | Not Suitable
    recommendation: str = ""          # Proceed | Hold | Reject
    strengths: list = field(default_factory=list)
    weaknesses: list = field(default_factory=list)
    summary: str = ""
    rubric: dict = field(default_factory=dict)

    def to_dict(self):
        return asdict(self)


@dataclass
class CallEvent:
    """One event on the Redis stream `calls:events` (consumer groups per
    subscriber: django-callback, websocket, metrics)."""
    call_id: str                      # platform call id (uuid)
    ats_call_id: int                  # AICall.id in the ATS
    state: CallState
    at_ms: int                        # epoch ms (producers stamp this)
    reason: str = ""                  # failure reason / hangup cause
    utterances: list = field(default_factory=list)     # list[Utterance.to_dict()]
    evaluation: Optional[dict] = None                  # Evaluation.to_dict()
    duration_s: Optional[int] = None

    def to_dict(self):
        d = asdict(self)
        d["state"] = self.state.value
        return d
