"""
数据模型定义模块

定义题目和标签的数据模型，使用 Pydantic 进行数据验证。
"""

from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel, ConfigDict, Field, field_validator


class QuestionModel(BaseModel):
    """
    题目数据模型
    
    定义题目的完整数据结构，包含所有必需和可选字段。
    使用 Pydantic 进行数据验证，确保数据完整性。
    """
    
    # 必填字段
    question_id: str = Field(..., description="题目唯一标识符（UUID）")
    title: str = Field(..., min_length=1, max_length=200, description="题目标题")
    content: str = Field(..., min_length=1, max_length=10000, description="题目完整内容")
    question_type: str = Field(..., description="题型（单选/多选/判断/填空/简答）")
    category: str = Field(..., min_length=1, description="题目分类")
    difficulty: str = Field(..., description="难度等级（简单/中等/困难）")
    status: str = Field(default="草稿", description="状态（草稿/已发布/已归档）")
    created_at: str = Field(..., description="创建时间（ISO 8601格式）")
    updated_at: str = Field(..., description="更新时间（ISO 8601格式）")
    
    # 可选字段
    tags: List[str] = Field(default_factory=list, max_length=10, description="题目标签")
    answer: Optional[str] = Field(default=None, description="参考答案")
    explanation: Optional[str] = Field(default=None, description="答案解析")
    source: Optional[str] = Field(default=None, description="题目来源")
    source_url: Optional[str] = Field(default=None, description="来源链接")
    points: Optional[int] = Field(default=None, ge=0, description="题目分值")
    usage_count: int = Field(default=0, ge=0, description="使用次数")
    correct_rate: Optional[float] = Field(default=None, ge=0.0, le=1.0, description="正确率（0-1）")
    created_by: Optional[str] = Field(default=None, description="创建人")
    
    @field_validator("question_type")
    @classmethod
    def validate_question_type(cls, v: str) -> str:
        """验证题型是否合法"""
        valid_types = ["单选", "多选", "判断", "填空", "简答"]
        if v not in valid_types:
            raise ValueError(f"题型必须是以下之一：{', '.join(valid_types)}")
        return v
    
    @field_validator("difficulty")
    @classmethod
    def validate_difficulty(cls, v: str) -> str:
        """验证难度等级是否合法"""
        valid_difficulties = ["简单", "中等", "困难"]
        if v not in valid_difficulties:
            raise ValueError(f"难度等级必须是以下之一：{', '.join(valid_difficulties)}")
        return v
    
    @field_validator("status")
    @classmethod
    def validate_status(cls, v: str) -> str:
        """验证状态是否合法"""
        valid_statuses = ["草稿", "已发布", "已归档"]
        if v not in valid_statuses:
            raise ValueError(f"状态必须是以下之一：{', '.join(valid_statuses)}")
        return v
    
    @field_validator("tags")
    @classmethod
    def validate_tags(cls, v: List[str]) -> List[str]:
        """验证标签列表"""
        if len(v) > 10:
            raise ValueError("标签数量不能超过10个")
        # 去除重复标签
        return list(set(v))
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "question_id": "550e8400-e29b-41d4-a716-446655440000",
                "title": "Python基础：列表推导式",
                "content": "以下哪个选项能正确创建一个包含1到10的平方数的列表？\nA. [x^2 for x in range(1, 11)]\nB. [x**2 for x in range(1, 11)]\nC. [x*x for x in range(1, 11)]\nD. B和C都正确",
                "question_type": "单选",
                "category": "Python编程",
                "difficulty": "简单",
                "status": "已发布",
                "tags": ["Python", "列表推导式", "基础语法"],
                "answer": "D",
                "explanation": "在Python中，**是幂运算符，x**2和x*x都可以计算平方。",
                "source": "Python官方教程",
                "points": 5,
                "created_at": "2024-01-01T00:00:00Z",
                "updated_at": "2024-01-01T00:00:00Z"
            }
        }
    )


class TagModel(BaseModel):
    """
    标签数据模型
    
    定义标签的数据结构，用于题目分类和检索。
    """
    
    tag_id: Optional[int] = Field(default=None, description="标签ID（自增，数据库生成）")
    tag_name: str = Field(..., min_length=1, max_length=50, description="标签名称")
    usage_count: int = Field(default=0, ge=0, description="使用次数")
    
    @field_validator("tag_name")
    @classmethod
    def validate_tag_name(cls, v: str) -> str:
        """验证标签名称格式"""
        # 去除首尾空格
        v = v.strip()
        if not v:
            raise ValueError("标签名称不能为空")
        if len(v) > 50:
            raise ValueError("标签名称长度不能超过50个字符")
        return v
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "tag_id": 1,
                "tag_name": "Python",
                "usage_count": 150
            }
        }
    )


class QuestionTagRelation(BaseModel):
    """
    题目-标签关联关系模型
    
    定义题目和标签之间的多对多关系。
    """
    
    question_id: str = Field(..., description="题目ID")
    tag_id: int = Field(..., description="标签ID")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "question_id": "550e8400-e29b-41d4-a716-446655440000",
                "tag_id": 1
            }
        }
    )


class QuestionCreateDTO(BaseModel):
    """
    题目创建数据传输对象
    
    用于创建题目时的数据验证，不包含自动生成的字段。
    """
    
    title: str = Field(..., min_length=1, max_length=200, description="题目标题")
    content: str = Field(..., min_length=1, max_length=10000, description="题目内容")
    question_type: str = Field(..., description="题型")
    category: str = Field(..., min_length=1, description="分类")
    difficulty: str = Field(..., description="难度等级")
    tags: List[str] = Field(default_factory=list, max_length=10, description="标签")
    answer: Optional[str] = Field(default=None, description="参考答案")
    explanation: Optional[str] = Field(default=None, description="答案解析")
    source: Optional[str] = Field(default=None, description="来源")
    source_url: Optional[str] = Field(default=None, description="来源链接")
    points: Optional[int] = Field(default=None, ge=0, description="分值")
    status: str = Field(default="草稿", description="状态")
    created_by: Optional[str] = Field(default=None, description="创建人")


class QuestionUpdateDTO(BaseModel):
    """
    题目更新数据传输对象
    
    用于更新题目时的数据验证，所有字段都是可选的。
    """
    
    title: Optional[str] = Field(default=None, min_length=1, max_length=200, description="题目标题")
    content: Optional[str] = Field(default=None, min_length=1, max_length=10000, description="题目内容")
    question_type: Optional[str] = Field(default=None, description="题型")
    category: Optional[str] = Field(default=None, min_length=1, description="分类")
    difficulty: Optional[str] = Field(default=None, description="难度等级")
    tags: Optional[List[str]] = Field(default=None, max_length=10, description="标签")
    answer: Optional[str] = Field(default=None, description="参考答案")
    explanation: Optional[str] = Field(default=None, description="答案解析")
    source: Optional[str] = Field(default=None, description="来源")
    source_url: Optional[str] = Field(default=None, description="来源链接")
    points: Optional[int] = Field(default=None, ge=0, description="分值")
    status: Optional[str] = Field(default=None, description="状态")
    
    @field_validator("*", mode="before")
    @classmethod
    def check_not_all_none(cls, v, info):
        """确保至少有一个字段被更新"""
        return v


class QuestionSearchFilter(BaseModel):
    """
    题目检索过滤条件
    
    用于检索和列表查询时的参数验证。
    """
    
    category: Optional[str] = Field(default=None, description="分类过滤")
    difficulty: Optional[str] = Field(default=None, description="难度过滤")
    question_type: Optional[str] = Field(default=None, description="题型过滤")
    status: Optional[str] = Field(default=None, description="状态过滤")
    tags: Optional[List[str]] = Field(default=None, description="标签过滤")
    min_points: Optional[int] = Field(default=None, ge=0, description="最小分值")
    max_points: Optional[int] = Field(default=None, ge=0, description="最大分值")
    created_after: Optional[str] = Field(default=None, description="创建时间起始")
    created_before: Optional[str] = Field(default=None, description="创建时间截止")


class QualityMetrics(BaseModel):
    """
    题目质量评估指标
    
    用于评估题目的质量和完整度。
    """
    
    question_id: str = Field(..., description="题目ID")
    has_answer: bool = Field(default=False, description="是否有答案")
    has_explanation: bool = Field(default=False, description="是否有解析")
    has_tags: bool = Field(default=False, description="是否有标签")
    title_length: int = Field(default=0, ge=0, description="标题长度")
    content_length: int = Field(default=0, ge=0, description="内容长度")
    answer_length: int = Field(default=0, ge=0, description="答案长度")
    explanation_length: int = Field(default=0, ge=0, description="解析长度")
    tags_count: int = Field(default=0, ge=0, description="标签数量")
    completeness_score: float = Field(default=0.0, ge=0.0, le=100.0, description="完整度评分（0-100）")
    quality_score: float = Field(default=0.0, ge=0.0, le=100.0, description="质量评分（0-100）")


class CategoryStatistics(BaseModel):
    """
    分类统计信息
    
    统计各分类的题目数量、难度分布等。
    """
    
    category: str = Field(..., description="分类名称")
    total_count: int = Field(default=0, ge=0, description="题目总数")
    easy_count: int = Field(default=0, ge=0, description="简单题数量")
    medium_count: int = Field(default=0, ge=0, description="中等题数量")
    hard_count: int = Field(default=0, ge=0, description="困难题数量")
    published_count: int = Field(default=0, ge=0, description="已发布题数")
    draft_count: int = Field(default=0, ge=0, description="草稿题数")
    archived_count: int = Field(default=0, ge=0, description="已归档题数")
    average_points: Optional[float] = Field(default=None, description="平均分值")
    total_points: int = Field(default=0, ge=0, description="总分值")


class DifficultyStatistics(BaseModel):
    """
    难度分布统计
    
    统计各难度级别的题目数量和分布。
    """
    
    difficulty: str = Field(..., description="难度等级")
    count: int = Field(default=0, ge=0, description="题目数量")
    percentage: float = Field(default=0.0, ge=0.0, le=100.0, description="占比（%）")
    average_correct_rate: Optional[float] = Field(default=None, ge=0.0, le=1.0, description="平均正确率")
    average_usage_count: float = Field(default=0.0, ge=0.0, description="平均使用次数")


class TagStatistics(BaseModel):
    """
    标签统计信息
    
    统计各标签的使用情况。
    """
    
    tag_name: str = Field(..., description="标签名称")
    usage_count: int = Field(default=0, ge=0, description="使用次数")
    question_count: int = Field(default=0, ge=0, description="关联题目数")
    average_difficulty: Optional[float] = Field(default=None, description="平均难度（数值）")


class TimeSeriesData(BaseModel):
    """
    时间序列数据
    
    用于时间序列分析。
    """
    
    timestamp: str = Field(..., description="时间戳（ISO 8601格式）")
    date: str = Field(..., description="日期（YYYY-MM-DD格式）")
    period: str = Field(..., description="时期（day/week/month）")
    questions_created: int = Field(default=0, ge=0, description="新增题目数")
    questions_updated: int = Field(default=0, ge=0, description="更新题目数")
    questions_deleted: int = Field(default=0, ge=0, description="删除题目数")
    cumulative_total: int = Field(default=0, ge=0, description="累计题目数")


class OverallStatistics(BaseModel):
    """
    整体统计概览
    
    汇总所有主要统计指标。
    """
    
    total_questions: int = Field(default=0, ge=0, description="题目总数")
    published_questions: int = Field(default=0, ge=0, description="已发布题数")
    draft_questions: int = Field(default=0, ge=0, description="草稿题数")
    archived_questions: int = Field(default=0, ge=0, description="已归档题数")
    total_tags: int = Field(default=0, ge=0, description="总标签数")
    total_categories: int = Field(default=0, ge=0, description="总分类数")
    average_points: Optional[float] = Field(default=None, description="平均分值")
    total_points: int = Field(default=0, ge=0, description="总分值")
    average_correct_rate: Optional[float] = Field(default=None, ge=0.0, le=1.0, description="平均正确率")
    average_usage_count: float = Field(default=0.0, ge=0.0, description="平均使用次数")
    total_usage_count: int = Field(default=0, ge=0, description="总使用次数")
    last_updated: str = Field(..., description="最后更新时间")
    statistics_timestamp: str = Field(..., description="统计时间戳")
