"""Pydantic models for the KOAN decision graph node types."""

from __future__ import annotations

from datetime import datetime  # noqa: TCH003  # Pydantic needs at runtime
from typing import Any, Literal

from pydantic import BaseModel, Field


class DecisionNode(BaseModel):
    """A discrete decision point in an agent run."""

    decision_id: str
    run_id: str
    timestamp: datetime
    description: str
    confidence: float = Field(ge=0.0, le=1.0)
    reasoning: str
    decision_type: Literal[
        "classification",
        "routing",
        "tool_selection",
        "policy_eval",
        "exception",
        "approval",
        "output",
    ]
    inputs: dict[str, Any] = Field(default_factory=dict)
    metadata: dict[str, Any] = Field(default_factory=dict)


class ActionNode(BaseModel):
    """A concrete action taken as result of a decision."""

    action_id: str
    action_type: Literal["tool_call", "llm_call", "handoff", "api_call", "human_review"]
    tool_name: str | None = None
    input: dict[str, Any] = Field(default_factory=dict)
    output: Any = None
    latency_ms: int | None = None
    error: str | None = None


class PolicyNode(BaseModel):
    """A policy or rule set that governed a decision."""

    policy_id: str
    name: str
    version: str
    description: str
    rules: list[str] = Field(default_factory=list)
    source: str | None = None


class ExceptionNode(BaseModel):
    """An exception to policy — the override and who approved it."""

    exception_id: str
    reason: str
    approved_by: str | None = None
    approved_at: datetime | None = None
    precedent_ref: str | None = None


class OutcomeNode(BaseModel):
    """Result of an agent run."""

    outcome_id: str
    run_id: str
    status: Literal["success", "failure", "partial", "pending_review"]
    result: Any = None
    evaluation_score: float | None = None
    evaluated_by: str | None = None


class EntityRef(BaseModel):
    """A business entity referenced in a decision."""

    entity_id: str
    entity_type: str
    source_system: str = ""
    external_id: str | None = None
    properties: dict[str, Any] = Field(default_factory=dict)


class RunNode(BaseModel):
    """A single agent execution run."""

    run_id: str
    thread_id: str
    agent_id: str
    started_at: datetime
    ended_at: datetime | None = None
    status: Literal["running", "completed", "failed"] = "running"
    trigger: str | None = None


class FeedbackNode(BaseModel):
    """User feedback on an agent run outcome."""

    feedback_id: str
    feedback_type: Literal["explicit", "fork", "rewind", "thumbs_up", "thumbs_down"]
    score: float = Field(ge=-1.0, le=1.0)
    comment: str = ""
    timestamp: datetime | None = None


class AgentNode(BaseModel):
    """An agent in the KOAN framework."""

    agent_id: str
    name: str
    agent_type: str = ""
    model: str = ""
    version: str = ""
