"""
课程相关的数据验证模型
"""
from typing import Optional, List
from datetime import datetime
from enum import Enum

from pydantic import BaseModel, Field, ConfigDict, field_validator

from app.models.course import CourseStatus, CourseCategory


class CourseBase(BaseModel):
    """
    课程基础模型
    """

    name: str = Field(..., min_length=1, max_length=200, description="课程名称")
    description: Optional[str] = Field(None, description="课程描述")
    category: CourseCategory = Field(default=CourseCategory.GENERAL, description="课程分类")
    cover_image: Optional[str] = Field(None, max_length=500, description="封面图片URL")
    duration_hours: Optional[float] = Field(None, ge=0, description="课程时长(小时)")
    difficulty_level: Optional[int] = Field(None, ge=1, le=5, description="难度等级(1-5)")
    tags: Optional[List[str]] = Field(default_factory=list, description="标签列表")
    sort_order: int = Field(default=0, description="排序顺序")
    is_featured: bool = Field(default=False, description="是否推荐")
    allow_download: bool = Field(default=False, description="是否允许下载资料")

    @field_validator("category", mode="before")
    @classmethod
    def normalize_category(cls, v):
        """允许使用枚举的名称或值（忽略大小写）。空字符串使用默认值。"""
        if isinstance(v, CourseCategory):
            return v
        if isinstance(v, str):
            s = v.strip()
            # 空字符串使用默认值
            if not s:
                return CourseCategory.GENERAL
            # 优先按值匹配（technology 等）
            try:
                return CourseCategory(s.lower())
            except Exception:
                pass
            # 再按名称匹配（TECHNOLOGY 等）
            try:
                return CourseCategory[s.upper()]
            except Exception:
                pass
        return v


class CourseCreate(CourseBase):
    """
    创建课程模型
    """

    status: CourseStatus = Field(default=CourseStatus.DRAFT, description="课程状态")


class CourseUpdate(BaseModel):
    """
    更新课程模型
    """

    name: Optional[str] = Field(None, min_length=1, max_length=200, description="课程名称")
    description: Optional[str] = Field(None, description="课程描述")
    category: Optional[CourseCategory] = Field(None, description="课程分类")
    status: Optional[CourseStatus] = Field(None, description="课程状态")
    cover_image: Optional[str] = Field(None, max_length=500, description="封面图片URL")
    duration_hours: Optional[float] = Field(None, ge=0, description="课程时长(小时)")
    difficulty_level: Optional[int] = Field(None, ge=1, le=5, description="难度等级(1-5)")
    tags: Optional[List[str]] = Field(None, description="标签列表")
    sort_order: Optional[int] = Field(None, description="排序顺序")
    is_featured: Optional[bool] = Field(None, description="是否推荐")
    allow_download: Optional[bool] = Field(None, description="是否允许下载资料")

    @field_validator("category", mode="before")
    @classmethod
    def normalize_category_update(cls, v):
        if v is None:
            return v
        if isinstance(v, CourseCategory):
            return v
        if isinstance(v, str):
            s = v.strip()
            if not s:  # 空字符串视为None（不更新）
                return None
            try:
                return CourseCategory(s.lower())
            except Exception:
                pass
            try:
                return CourseCategory[s.upper()]
            except Exception:
                pass
        return v


class CourseInDB(CourseBase):
    """
    数据库中的课程模型
    """

    model_config = ConfigDict(from_attributes=True)

    id: int = Field(..., description="课程ID")
    status: CourseStatus = Field(..., description="课程状态")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")
    published_at: Optional[datetime] = Field(None, description="发布时间")
    publisher_id: Optional[int] = Field(None, description="发布人ID")
    created_by: Optional[int] = Field(None, description="创建人ID")
    updated_by: Optional[int] = Field(None, description="更新人ID")
    # 用户岗位相关的课程类型（必修/选修），非数据库字段，由API动态计算
    course_type: Optional[str] = Field(None, description="课程类型：required=必修, optional=选修")


class CourseList(BaseModel):
    """
    课程列表查询参数
    """

    status: Optional[CourseStatus] = Field(None, description="课程状态")
    category: Optional[CourseCategory] = Field(None, description="课程分类")
    is_featured: Optional[bool] = Field(None, description="是否推荐")
    keyword: Optional[str] = Field(None, description="搜索关键词")


# 课程资料相关模型
class CourseMaterialBase(BaseModel):
    """
    课程资料基础模型
    """

    name: str = Field(..., min_length=1, max_length=200, description="资料名称")
    description: Optional[str] = Field(None, description="资料描述")
    sort_order: int = Field(default=0, description="排序顺序")


class CourseMaterialCreate(CourseMaterialBase):
    """
    创建课程资料模型
    """

    file_url: str = Field(..., max_length=500, description="文件URL")
    file_type: str = Field(..., max_length=50, description="文件类型")
    file_size: int = Field(..., gt=0, description="文件大小(字节)")

    @field_validator("file_type")
    def validate_file_type(cls, v):
        """验证文件类型
        支持格式：TXT、Markdown、MDX、PDF、HTML、Excel、Word、CSV、VTT、Properties
        """
        allowed_types = [
            "txt", "md", "mdx", "pdf", "html", "htm",
            "xlsx", "xls", "docx", "doc", "csv", "vtt", "properties"
        ]
        file_ext = v.lower()
        if file_ext not in allowed_types:
            raise ValueError(f"不支持的文件类型: {v}。允许的类型: TXT、Markdown、MDX、PDF、HTML、Excel、Word、CSV、VTT、Properties")
        return file_ext


class CourseMaterialInDB(CourseMaterialBase):
    """
    数据库中的课程资料模型
    """

    model_config = ConfigDict(from_attributes=True)

    id: int = Field(..., description="资料ID")
    course_id: int = Field(..., description="课程ID")
    file_url: str = Field(..., description="文件URL")
    file_type: str = Field(..., description="文件类型")
    file_size: int = Field(..., description="文件大小(字节)")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")


# 知识点相关模型
class KnowledgePointBase(BaseModel):
    """
    知识点基础模型
    """

    name: str = Field(..., min_length=1, max_length=200, description="知识点名称")
    description: Optional[str] = Field(None, description="知识点描述")
    type: str = Field(default="理论知识", description="知识点类型")
    source: int = Field(default=0, description="来源：0=手动，1=AI分析")
    topic_relation: Optional[str] = Field(None, description="与主题的关系描述")


class KnowledgePointCreate(KnowledgePointBase):
    """
    创建知识点模型
    """

    material_id: int = Field(..., description="关联资料ID（必填）")


class KnowledgePointUpdate(BaseModel):
    """
    更新知识点模型
    """

    name: Optional[str] = Field(None, min_length=1, max_length=200, description="知识点名称")
    description: Optional[str] = Field(None, description="知识点描述")
    type: Optional[str] = Field(None, description="知识点类型")
    source: Optional[int] = Field(None, description="来源：0=手动，1=AI分析")
    topic_relation: Optional[str] = Field(None, description="与主题的关系描述")
    material_id: int = Field(..., description="关联资料ID（必填）")


class KnowledgePointInDB(KnowledgePointBase):
    """
    数据库中的知识点模型
    """

    model_config = ConfigDict(from_attributes=True)

    id: int = Field(..., description="知识点ID")
    course_id: int = Field(..., description="课程ID")
    material_id: int = Field(..., description="关联资料ID")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")


class KnowledgePointTree(KnowledgePointInDB):
    """
    知识点树形结构
    """

    children: List["KnowledgePointTree"] = Field(
        default_factory=list, description="子知识点"
    )


# 成长路径相关模型
class GrowthPathCourse(BaseModel):
    """
    成长路径中的课程
    """

    course_id: int = Field(..., description="课程ID")
    order: int = Field(..., ge=0, description="排序")
    is_required: bool = Field(default=True, description="是否必修")


class GrowthPathBase(BaseModel):
    """
    成长路径基础模型
    """

    name: str = Field(..., min_length=1, max_length=200, description="路径名称")
    description: Optional[str] = Field(None, description="路径描述")
    target_role: Optional[str] = Field(None, max_length=100, description="目标角色")
    courses: List[GrowthPathCourse] = Field(default_factory=list, description="课程列表")
    estimated_duration_days: Optional[int] = Field(None, ge=1, description="预计完成天数")
    is_active: bool = Field(default=True, description="是否启用")
    sort_order: int = Field(default=0, description="排序顺序")


class GrowthPathCreate(GrowthPathBase):
    """
    创建成长路径模型
    """

    pass


class GrowthPathInDB(GrowthPathBase):
    """
    数据库中的成长路径模型
    """

    model_config = ConfigDict(from_attributes=True)

    id: int = Field(..., description="路径ID")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")


# 课程考试设置相关Schema
class CourseExamSettingsBase(BaseModel):
    """
    课程考试设置基础模型
    """
    single_choice_count: int = Field(default=4, ge=0, le=50, description="单选题数量")
    multiple_choice_count: int = Field(default=2, ge=0, le=30, description="多选题数量")
    true_false_count: int = Field(default=1, ge=0, le=20, description="判断题数量")
    fill_blank_count: int = Field(default=2, ge=0, le=10, description="填空题数量")
    essay_count: int = Field(default=1, ge=0, le=10, description="问答题数量")
    
    duration_minutes: int = Field(default=10, ge=10, le=180, description="考试时长(分钟)")
    difficulty_level: int = Field(default=3, ge=1, le=5, description="难度系数(1-5)")
    passing_score: int = Field(default=60, ge=0, le=100, description="及格分数")
    
    is_enabled: bool = Field(default=True, description="是否启用")
    show_answer_immediately: bool = Field(default=False, description="是否立即显示答案")
    allow_retake: bool = Field(default=True, description="是否允许重考")
    max_retake_times: Optional[int] = Field(None, ge=1, le=10, description="最大重考次数")


class CourseExamSettingsCreate(CourseExamSettingsBase):
    """
    创建课程考试设置模型
    """
    pass


class CourseExamSettingsUpdate(BaseModel):
    """
    更新课程考试设置模型
    """
    single_choice_count: Optional[int] = Field(None, ge=0, le=50, description="单选题数量")
    multiple_choice_count: Optional[int] = Field(None, ge=0, le=30, description="多选题数量")
    true_false_count: Optional[int] = Field(None, ge=0, le=20, description="判断题数量")
    fill_blank_count: Optional[int] = Field(None, ge=0, le=10, description="填空题数量")
    essay_count: Optional[int] = Field(None, ge=0, le=10, description="问答题数量")
    
    duration_minutes: Optional[int] = Field(None, ge=10, le=180, description="考试时长(分钟)")
    difficulty_level: Optional[int] = Field(None, ge=1, le=5, description="难度系数(1-5)")
    passing_score: Optional[int] = Field(None, ge=0, le=100, description="及格分数")
    
    is_enabled: Optional[bool] = Field(None, description="是否启用")
    show_answer_immediately: Optional[bool] = Field(None, description="是否立即显示答案")
    allow_retake: Optional[bool] = Field(None, description="是否允许重考")
    max_retake_times: Optional[int] = Field(None, ge=1, le=10, description="最大重考次数")


class CourseExamSettingsInDB(CourseExamSettingsBase):
    """
    数据库中的课程考试设置模型
    """
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(..., description="设置ID")
    course_id: int = Field(..., description="课程ID")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")


# 岗位分配相关Schema
class CoursePositionAssignment(BaseModel):
    """
    课程岗位分配模型
    """
    position_id: int = Field(..., description="岗位ID")
    course_type: str = Field(default="required", pattern="^(required|optional)$", description="课程类型：required必修/optional选修")
    priority: int = Field(default=0, description="优先级/排序")


class CoursePositionAssignmentInDB(CoursePositionAssignment):
    """
    数据库中的课程岗位分配模型
    """
    model_config = ConfigDict(from_attributes=True)
    
    id: int = Field(..., description="分配ID")
    course_id: int = Field(..., description="课程ID")
    position_name: Optional[str] = Field(None, description="岗位名称")
    position_description: Optional[str] = Field(None, description="岗位描述")
    member_count: Optional[int] = Field(None, description="岗位成员数")
