"""陪练模块数据模型"""
from datetime import datetime
from typing import Optional
from enum import Enum

from sqlalchemy import (
    Column,
    String,
    Integer,
    ForeignKey,
    Text,
    JSON,
    Enum as SQLEnum,
    Float,
    Boolean,
    DateTime,
    func,
)
from sqlalchemy.orm import relationship, Mapped, mapped_column

from app.models.base import BaseModel, SoftDeleteMixin, AuditMixin


class TrainingSceneStatus(str, Enum):
    """陪练场景状态枚举"""

    DRAFT = "draft"  # 草稿
    ACTIVE = "active"  # 已激活
    INACTIVE = "inactive"  # 已停用


class TrainingSessionStatus(str, Enum):
    """陪练会话状态枚举"""

    CREATED = "created"  # 已创建
    IN_PROGRESS = "in_progress"  # 进行中
    COMPLETED = "completed"  # 已完成
    CANCELLED = "cancelled"  # 已取消
    ERROR = "error"  # 异常结束


class MessageType(str, Enum):
    """消息类型枚举"""

    TEXT = "text"  # 文本消息
    VOICE = "voice"  # 语音消息
    SYSTEM = "system"  # 系统消息


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

    USER = "user"  # 用户
    ASSISTANT = "assistant"  # AI助手
    SYSTEM = "system"  # 系统


class TrainingScene(BaseModel, SoftDeleteMixin, AuditMixin):
    """
    陪练场景模型
    定义不同的陪练场景，如面试训练、演讲训练等
    """

    __tablename__ = "training_scenes"
    __allow_unmapped__ = True

    # 基础信息
    name: Mapped[str] = mapped_column(String(100), nullable=False, comment="场景名称")
    description: Mapped[Optional[str]] = mapped_column(
        Text, nullable=True, comment="场景描述"
    )
    category: Mapped[str] = mapped_column(String(50), nullable=False, comment="场景分类")

    # 配置信息
    ai_config: Mapped[Optional[dict]] = mapped_column(
        JSON, nullable=True, comment="AI配置（如Coze Bot ID等）"
    )
    prompt_template: Mapped[Optional[str]] = mapped_column(
        Text, nullable=True, comment="提示词模板"
    )
    evaluation_criteria: Mapped[Optional[dict]] = mapped_column(
        JSON, nullable=True, comment="评估标准"
    )

    # 状态和权限
    status: Mapped[TrainingSceneStatus] = mapped_column(
        SQLEnum(TrainingSceneStatus),
        default=TrainingSceneStatus.DRAFT,
        nullable=False,
        comment="场景状态",
    )
    is_public: Mapped[bool] = mapped_column(
        Boolean, default=True, nullable=False, comment="是否公开"
    )
    required_level: Mapped[Optional[int]] = mapped_column(
        Integer, nullable=True, comment="所需用户等级"
    )

    # 关联
    sessions: Mapped[list["TrainingSession"]] = relationship(
        "TrainingSession", back_populates="scene", cascade="all, delete-orphan"
    )


class TrainingSession(BaseModel, AuditMixin):
    """
    陪练会话模型
    记录每次陪练会话的信息
    """

    __tablename__ = "training_sessions"
    __allow_unmapped__ = True

    # 基础信息
    user_id: Mapped[int] = mapped_column(
        Integer, nullable=False, index=True, comment="用户ID"
    )
    scene_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("training_scenes.id"), nullable=False, comment="场景ID"
    )

    # 会话信息
    coze_conversation_id: Mapped[Optional[str]] = mapped_column(
        String(100), nullable=True, comment="Coze会话ID"
    )
    start_time: Mapped[datetime] = mapped_column(
        DateTime, server_default=func.now(), nullable=False, comment="开始时间（北京时间）"
    )
    end_time: Mapped[Optional[datetime]] = mapped_column(
        DateTime, nullable=True, comment="结束时间（北京时间）"
    )
    duration_seconds: Mapped[Optional[int]] = mapped_column(
        Integer, nullable=True, comment="持续时长（秒）"
    )

    # 状态和配置
    status: Mapped[TrainingSessionStatus] = mapped_column(
        SQLEnum(TrainingSessionStatus),
        default=TrainingSessionStatus.CREATED,
        nullable=False,
        comment="会话状态",
    )
    session_config: Mapped[Optional[dict]] = mapped_column(
        JSON, nullable=True, comment="会话配置"
    )

    # 评估信息
    total_score: Mapped[Optional[float]] = mapped_column(
        Float, nullable=True, comment="总分"
    )
    evaluation_result: Mapped[Optional[dict]] = mapped_column(
        JSON, nullable=True, comment="评估结果详情"
    )

    # 关联
    scene: Mapped["TrainingScene"] = relationship(
        "TrainingScene", back_populates="sessions"
    )
    messages: Mapped[list["TrainingMessage"]] = relationship(
        "TrainingMessage",
        back_populates="session",
        cascade="all, delete-orphan",
        order_by="TrainingMessage.created_at",
    )
    report: Mapped[Optional["TrainingReport"]] = relationship(
        "TrainingReport", back_populates="session", uselist=False
    )


class TrainingMessage(BaseModel):
    """
    陪练消息模型
    记录会话中的每条消息
    """

    __tablename__ = "training_messages"
    __allow_unmapped__ = True

    # 基础信息
    session_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("training_sessions.id"), nullable=False, comment="会话ID"
    )

    # 消息内容
    role: Mapped[MessageRole] = mapped_column(
        SQLEnum(MessageRole), nullable=False, comment="消息角色"
    )
    type: Mapped[MessageType] = mapped_column(
        SQLEnum(MessageType), nullable=False, comment="消息类型"
    )
    content: Mapped[str] = mapped_column(Text, nullable=False, comment="消息内容")

    # 语音消息相关
    voice_url: Mapped[Optional[str]] = mapped_column(
        String(500), nullable=True, comment="语音文件URL"
    )
    voice_duration: Mapped[Optional[float]] = mapped_column(
        Float, nullable=True, comment="语音时长（秒）"
    )

    # 元数据
    message_metadata: Mapped[Optional[dict]] = mapped_column(
        JSON, nullable=True, comment="消息元数据"
    )
    coze_message_id: Mapped[Optional[str]] = mapped_column(
        String(100), nullable=True, comment="Coze消息ID"
    )

    # 关联
    session: Mapped["TrainingSession"] = relationship(
        "TrainingSession", back_populates="messages"
    )


class TrainingReport(BaseModel, AuditMixin):
    """
    陪练报告模型
    存储陪练会话的分析报告
    """

    __tablename__ = "training_reports"
    __allow_unmapped__ = True

    # 基础信息
    session_id: Mapped[int] = mapped_column(
        Integer,
        ForeignKey("training_sessions.id"),
        unique=True,
        nullable=False,
        comment="会话ID",
    )
    user_id: Mapped[int] = mapped_column(
        Integer, nullable=False, index=True, comment="用户ID"
    )

    # 评分信息
    overall_score: Mapped[float] = mapped_column(Float, nullable=False, comment="总体得分")
    dimension_scores: Mapped[dict] = mapped_column(
        JSON, nullable=False, comment="各维度得分"
    )

    # 分析内容
    strengths: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="优势点")
    weaknesses: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="待改进点")
    suggestions: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="改进建议")

    # 详细内容
    detailed_analysis: Mapped[Optional[str]] = mapped_column(
        Text, nullable=True, comment="详细分析"
    )
    transcript: Mapped[Optional[str]] = mapped_column(
        Text, nullable=True, comment="对话文本记录"
    )

    # 统计信息
    statistics: Mapped[Optional[dict]] = mapped_column(
        JSON, nullable=True, comment="统计数据"
    )

    # 关联
    session: Mapped["TrainingSession"] = relationship(
        "TrainingSession", back_populates="report"
    )
