from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass(frozen=True)
class ConversationTurn:
    role: str
    content: str

    @classmethod
    def from_dict(cls, raw: dict[str, Any]) -> "ConversationTurn":
        return cls(
            role=str(raw.get("role", "user")),
            content=str(raw.get("content", "")).strip(),
        )


@dataclass(frozen=True)
class NEESRequest:
    message: str
    history: list[ConversationTurn] = field(default_factory=list)
    session_id: str = "default"
    metadata: dict[str, Any] = field(default_factory=dict)

    @classmethod
    def from_dict(cls, raw: dict[str, Any]) -> "NEESRequest":
        if "message" not in raw:
            raise ValueError("request must include a 'message' field")

        history = [
            ConversationTurn.from_dict(item)
            for item in raw.get("history", [])
            if isinstance(item, dict)
        ]
        metadata = raw.get("metadata", {})
        if not isinstance(metadata, dict):
            metadata = {}

        return cls(
            message=str(raw["message"]).strip(),
            history=history,
            session_id=str(raw.get("session_id", "default")),
            metadata=metadata,
        )

    def history_as_dicts(self) -> list[dict[str, str]]:
        return [{"role": item.role, "content": item.content} for item in self.history]


@dataclass(frozen=True)
class IntentResult:
    label: str
    confidence: float
    cues: list[str] = field(default_factory=list)


@dataclass(frozen=True)
class EmotionResult:
    state: str
    intensity: float
    urgency: str
    cues: list[str] = field(default_factory=list)


@dataclass(frozen=True)
class MemoryItem:
    content: str
    score: float
    source: str


@dataclass(frozen=True)
class DecisionResult:
    category: str
    framework: str
    goal: str
    system_prompt: str


@dataclass(frozen=True)
class BehaviorPlan:
    style: str
    structure: list[str]
    guardrails: list[str]
    instructions: list[str]


@dataclass(frozen=True)
class TraceStep:
    name: str
    payload: dict[str, Any]


@dataclass(frozen=True)
class NEESTrace:
    trace_id: str
    mode: str
    llm: str
    steps: list[TraceStep]
    summary: dict[str, Any]


@dataclass(frozen=True)
class ProcessResponse:
    text: str
    trace: NEESTrace
    mode: str
    session_id: str
    metadata: dict[str, Any] = field(default_factory=dict)
