from __future__ import annotations

from datetime import datetime
from typing import Any, Literal

from pydantic import BaseModel, Field

OrchestratorSource = Literal["user_message", "schedule", "system_event"]
OrchestratorAgent = Literal["user_agent", "hermes"]
OrchestratorStatus = Literal["succeeded", "blocked", "failed"]


class OrchestratorRequest(BaseModel):
    source: OrchestratorSource = Field(description="请求来源。")
    user_id: str | None = Field(default=None, description="当前用户 ID，任务触发可为空。")
    conversation_id: str | None = Field(default=None, description="多轮对话会话 ID。")
    message: str | None = Field(default=None, description="用户消息或任务描述。")
    task_id: str | None = Field(default=None, description="任务资产 ID，schedule 触发时优先使用。")
    context_json: dict[str, Any] = Field(
        default_factory=dict,
        description="用户上下文、测试开关或调用方附加信息。",
    )


class OrchestratorTraceSummary(BaseModel):
    scenario: str = Field(description="语义场景。")
    intent: str = Field(description="语义意图。")
    tool_count: int = Field(default=0, ge=0, description="工具调用总数。")
    failed_tool_count: int = Field(default=0, ge=0, description="失败工具调用数量。")
    selected_capability_codes: list[str] = Field(
        default_factory=list,
        description="本次路由命中的能力编码。",
    )
    degraded: bool = Field(default=False, description="是否发生降级。")


class OrchestratorResponse(BaseModel):
    run_id: str = Field(description="本次运行的唯一 run_id。")
    conversation_id: str | None = Field(default=None, description="当前会话 ID。")
    selected_agent: OrchestratorAgent | None = Field(
        default=None,
        description="最终路由到的下游 Agent。",
    )
    route_reason: str = Field(description="路由原因摘要。")
    permission_level: str = Field(description="权限级别。")
    status: OrchestratorStatus = Field(description="最终运行状态。")
    result: dict[str, Any] = Field(default_factory=dict, description="对前端可直接展示的最小结果。")
    requires_confirmation: bool = Field(default=False, description="是否需要用户或管理员确认。")
    trace_summary: OrchestratorTraceSummary = Field(description="简化后的 Trace 摘要。")


class ConversationMessageRead(BaseModel):
    id: str = Field(description="消息 ID。")
    role: str = Field(description="消息角色。")
    content: str = Field(description="消息正文。")
    run_id: str | None = Field(default=None, description="关联运行 ID。")
    message_json: dict[str, Any] = Field(default_factory=dict, description="扩展消息载荷。")
    created_at: datetime | None = Field(default=None, description="消息创建时间。")


class ConversationRead(BaseModel):
    conversation_id: str = Field(description="会话 ID。")
    user_id: str | None = Field(default=None, description="所属用户 ID。")
    source: str | None = Field(default=None, description="来源。")
    entry_source: str | None = Field(default=None, description="入口来源。")
    title: str | None = Field(default=None, description="会话标题。")
    last_run_id: str | None = Field(default=None, description="最近一次运行 ID。")
    last_scenario: str | None = Field(default=None, description="最近场景。")
    last_intent: str | None = Field(default=None, description="最近意图。")
    draft_claim_id: str | None = Field(default=None, description="关联草稿单 ID。")
    state_json: dict[str, Any] = Field(default_factory=dict, description="会话状态。")
    message_count: int = Field(default=0, ge=0, description="消息数量。")
    updated_at: datetime | None = Field(default=None, description="更新时间。")
    messages: list[ConversationMessageRead] = Field(default_factory=list, description="历史消息。")


class ConversationLookupResponse(BaseModel):
    found: bool = Field(default=False, description="是否找到可恢复会话。")
    conversation: ConversationRead | None = Field(default=None, description="会话详情。")


class ConversationDeleteResponse(BaseModel):
    deleted_count: int = Field(default=0, ge=0, description="删除的会话数量。")
