"""陪练模块Pydantic模式"""
from typing import Optional, List, Dict, Any, Generic, TypeVar
from datetime import datetime
from pydantic import BaseModel, Field, ConfigDict

# 定义泛型类型变量
DataT = TypeVar("DataT")

from app.models.training import (
    TrainingSceneStatus,
    TrainingSessionStatus,
    MessageType,
    MessageRole,
)
from app.schemas.base import BaseSchema, TimestampMixin, IDMixin


# ========== 陪练场景相关 ==========


class TrainingSceneBase(BaseSchema):
    """陪练场景基础模式"""

    name: str = Field(..., max_length=100, description="场景名称")
    description: Optional[str] = Field(None, description="场景描述")
    category: str = Field(..., max_length=50, description="场景分类")
    ai_config: Optional[Dict[str, Any]] = Field(None, description="AI配置")
    prompt_template: Optional[str] = Field(None, description="提示词模板")
    evaluation_criteria: Optional[Dict[str, Any]] = Field(None, description="评估标准")
    is_public: bool = Field(True, description="是否公开")
    required_level: Optional[int] = Field(None, description="所需用户等级")


class TrainingSceneCreate(TrainingSceneBase):
    """创建陪练场景模式"""

    status: TrainingSceneStatus = Field(
        default=TrainingSceneStatus.DRAFT, description="场景状态"
    )


class TrainingSceneUpdate(BaseSchema):
    """更新陪练场景模式"""

    name: Optional[str] = Field(None, max_length=100)
    description: Optional[str] = None
    category: Optional[str] = Field(None, max_length=50)
    ai_config: Optional[Dict[str, Any]] = None
    prompt_template: Optional[str] = None
    evaluation_criteria: Optional[Dict[str, Any]] = None
    status: Optional[TrainingSceneStatus] = None
    is_public: Optional[bool] = None
    required_level: Optional[int] = None


class TrainingSceneInDB(TrainingSceneBase, IDMixin, TimestampMixin):
    """数据库中的陪练场景模式"""

    status: TrainingSceneStatus
    is_deleted: bool = False
    created_by: Optional[int] = None
    updated_by: Optional[int] = None


class TrainingSceneResponse(TrainingSceneInDB):
    """陪练场景响应模式"""

    pass


# ========== 陪练会话相关 ==========


class TrainingSessionBase(BaseSchema):
    """陪练会话基础模式"""

    scene_id: int = Field(..., description="场景ID")
    session_config: Optional[Dict[str, Any]] = Field(None, description="会话配置")


class TrainingSessionCreate(TrainingSessionBase):
    """创建陪练会话模式"""

    pass


class TrainingSessionUpdate(BaseSchema):
    """更新陪练会话模式"""

    status: Optional[TrainingSessionStatus] = None
    end_time: Optional[datetime] = None
    duration_seconds: Optional[int] = None
    total_score: Optional[float] = None
    evaluation_result: Optional[Dict[str, Any]] = None


class TrainingSessionInDB(TrainingSessionBase, IDMixin, TimestampMixin):
    """数据库中的陪练会话模式"""

    user_id: int
    coze_conversation_id: Optional[str] = None
    start_time: datetime
    end_time: Optional[datetime] = None
    duration_seconds: Optional[int] = None
    status: TrainingSessionStatus
    total_score: Optional[float] = None
    evaluation_result: Optional[Dict[str, Any]] = None
    created_by: Optional[int] = None
    updated_by: Optional[int] = None


class TrainingSessionResponse(TrainingSessionInDB):
    """陪练会话响应模式"""

    scene: Optional["TrainingSceneResponse"] = None
    message_count: Optional[int] = Field(None, description="消息数量")


# ========== 消息相关 ==========


class TrainingMessageBase(BaseSchema):
    """陪练消息基础模式"""

    role: MessageRole = Field(..., description="消息角色")
    type: MessageType = Field(..., description="消息类型")
    content: str = Field(..., description="消息内容")
    voice_url: Optional[str] = Field(None, max_length=500, description="语音文件URL")
    voice_duration: Optional[float] = Field(None, description="语音时长（秒）")
    metadata: Optional[Dict[str, Any]] = Field(None, description="消息元数据")


class TrainingMessageCreate(TrainingMessageBase):
    """创建陪练消息模式"""

    session_id: int = Field(..., description="会话ID")
    coze_message_id: Optional[str] = Field(None, max_length=100, description="Coze消息ID")


class TrainingMessageInDB(TrainingMessageBase, IDMixin, TimestampMixin):
    """数据库中的陪练消息模式"""

    session_id: int
    coze_message_id: Optional[str] = None


class TrainingMessageResponse(TrainingMessageInDB):
    """陪练消息响应模式"""

    pass


# ========== 报告相关 ==========


class TrainingReportBase(BaseSchema):
    """陪练报告基础模式"""

    overall_score: float = Field(..., ge=0, le=100, description="总体得分")
    dimension_scores: Dict[str, float] = Field(..., description="各维度得分")
    strengths: List[str] = Field(..., description="优势点")
    weaknesses: List[str] = Field(..., description="待改进点")
    suggestions: List[str] = Field(..., description="改进建议")
    detailed_analysis: Optional[str] = Field(None, description="详细分析")
    transcript: Optional[str] = Field(None, description="对话文本记录")
    statistics: Optional[Dict[str, Any]] = Field(None, description="统计数据")


class TrainingReportCreate(TrainingReportBase):
    """创建陪练报告模式"""

    session_id: int = Field(..., description="会话ID")
    user_id: int = Field(..., description="用户ID")


class TrainingReportInDB(TrainingReportBase, IDMixin, TimestampMixin):
    """数据库中的陪练报告模式"""

    session_id: int
    user_id: int
    created_by: Optional[int] = None
    updated_by: Optional[int] = None


class TrainingReportResponse(TrainingReportInDB):
    """陪练报告响应模式"""

    session: Optional[TrainingSessionResponse] = None


# ========== 会话操作相关 ==========


class StartTrainingRequest(BaseSchema):
    """开始陪练请求"""

    scene_id: int = Field(..., description="场景ID")
    config: Optional[Dict[str, Any]] = Field(None, description="会话配置")


class StartTrainingResponse(BaseSchema):
    """开始陪练响应"""

    session_id: int = Field(..., description="会话ID")
    coze_conversation_id: Optional[str] = Field(None, description="Coze会话ID")
    scene: TrainingSceneResponse = Field(..., description="场景信息")
    websocket_url: Optional[str] = Field(None, description="WebSocket连接URL")


class EndTrainingRequest(BaseSchema):
    """结束陪练请求"""

    generate_report: bool = Field(True, description="是否生成报告")


class EndTrainingResponse(BaseSchema):
    """结束陪练响应"""

    session: TrainingSessionResponse = Field(..., description="会话信息")
    report: Optional[TrainingReportResponse] = Field(None, description="陪练报告")


# ========== 列表查询相关 ==========


class TrainingSceneListQuery(BaseSchema):
    """陪练场景列表查询参数"""

    category: Optional[str] = Field(None, description="场景分类")
    status: Optional[TrainingSceneStatus] = Field(None, description="场景状态")
    is_public: Optional[bool] = Field(None, description="是否公开")
    search: Optional[str] = Field(None, description="搜索关键词")
    page: int = Field(1, ge=1, description="页码")
    page_size: int = Field(20, ge=1, le=100, description="每页数量")


class TrainingSessionListQuery(BaseSchema):
    """陪练会话列表查询参数"""

    scene_id: Optional[int] = Field(None, description="场景ID")
    status: Optional[TrainingSessionStatus] = Field(None, description="会话状态")
    start_date: Optional[datetime] = Field(None, description="开始日期")
    end_date: Optional[datetime] = Field(None, description="结束日期")
    page: int = Field(1, ge=1, description="页码")
    page_size: int = Field(20, ge=1, le=100, description="每页数量")


class PaginatedResponse(BaseModel, Generic[DataT]):
    """分页响应模式"""

    items: List[DataT] = Field(..., description="数据列表")
    total: int = Field(..., description="总数量")
    page: int = Field(..., description="当前页码")
    page_size: int = Field(..., description="每页数量")
    pages: int = Field(..., description="总页数")


# 更新前向引用
TrainingSessionResponse.model_rebuild()
TrainingReportResponse.model_rebuild()
