"""
Coze 服务数据模型
"""

from typing import Optional, List, Dict, Any, Literal
from datetime import datetime
from pydantic import BaseModel, Field
from enum import Enum


class SessionType(str, Enum):
    """会话类型"""

    COURSE_CHAT = "course_chat"  # 课程对话
    TRAINING = "training"  # 陪练会话
    EXAM = "exam"  # 考试会话


class MessageRole(str, Enum):
    """消息角色"""

    USER = "user"
    ASSISTANT = "assistant"
    SYSTEM = "system"


class ContentType(str, Enum):
    """内容类型"""

    TEXT = "text"
    CARD = "card"
    IMAGE = "image"
    FILE = "file"


class StreamEventType(str, Enum):
    """流式事件类型"""

    MESSAGE_START = "conversation.message.start"
    MESSAGE_DELTA = "conversation.message.delta"
    MESSAGE_COMPLETED = "conversation.message.completed"
    ERROR = "error"
    DONE = "done"


class CozeSession(BaseModel):
    """Coze 会话模型"""

    session_id: str = Field(..., description="会话ID")
    conversation_id: str = Field(..., description="Coze对话ID")
    session_type: SessionType = Field(..., description="会话类型")
    user_id: str = Field(..., description="用户ID")
    bot_id: str = Field(..., description="Bot ID")
    created_at: datetime = Field(default_factory=datetime.now, description="创建时间")
    ended_at: Optional[datetime] = Field(None, description="结束时间")
    metadata: Dict[str, Any] = Field(default_factory=dict, description="元数据")

    class Config:
        json_encoders = {datetime: lambda v: v.isoformat()}


class CozeMessage(BaseModel):
    """Coze 消息模型"""

    message_id: str = Field(..., description="消息ID")
    session_id: str = Field(..., description="会话ID")
    role: MessageRole = Field(..., description="消息角色")
    content: str = Field(..., description="消息内容")
    content_type: ContentType = Field(ContentType.TEXT, description="内容类型")
    created_at: datetime = Field(default_factory=datetime.now, description="创建时间")
    metadata: Dict[str, Any] = Field(default_factory=dict, description="元数据")

    class Config:
        json_encoders = {datetime: lambda v: v.isoformat()}


class StreamEvent(BaseModel):
    """流式事件模型"""

    event: StreamEventType = Field(..., description="事件类型")
    data: Dict[str, Any] = Field(..., description="事件数据")
    message_id: Optional[str] = Field(None, description="消息ID")
    content: Optional[str] = Field(None, description="内容")
    content_type: Optional[ContentType] = Field(None, description="内容类型")
    role: Optional[MessageRole] = Field(None, description="角色")
    error: Optional[str] = Field(None, description="错误信息")


class CreateSessionRequest(BaseModel):
    """创建会话请求"""

    session_type: SessionType = Field(..., description="会话类型")
    user_id: str = Field(..., description="用户ID")
    course_id: Optional[str] = Field(None, description="课程ID (课程对话时必需)")
    training_topic: Optional[str] = Field(None, description="陪练主题 (陪练时可选)")
    metadata: Dict[str, Any] = Field(default_factory=dict, description="额外元数据")


class CreateSessionResponse(BaseModel):
    """创建会话响应"""

    session_id: str = Field(..., description="会话ID")
    conversation_id: str = Field(..., description="Coze对话ID")
    bot_id: str = Field(..., description="Bot ID")
    created_at: datetime = Field(..., description="创建时间")

    class Config:
        json_encoders = {datetime: lambda v: v.isoformat()}


class SendMessageRequest(BaseModel):
    """发送消息请求"""

    session_id: str = Field(..., description="会话ID")
    content: str = Field(..., description="消息内容")
    file_ids: List[str] = Field(default_factory=list, description="附件ID列表")
    stream: bool = Field(True, description="是否流式响应")


class EndSessionRequest(BaseModel):
    """结束会话请求"""

    reason: Optional[str] = Field(None, description="结束原因")
    feedback: Optional[Dict[str, Any]] = Field(None, description="用户反馈")


class EndSessionResponse(BaseModel):
    """结束会话响应"""

    session_id: str = Field(..., description="会话ID")
    ended_at: datetime = Field(..., description="结束时间")
    duration_seconds: int = Field(..., description="会话时长(秒)")
    message_count: int = Field(..., description="消息数量")

    class Config:
        json_encoders = {datetime: lambda v: v.isoformat()}
