"""QuizTrainer 数据模型定义."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from typing import Any


class QuestionType(str, Enum):
    """题目类型枚举."""

    CHOICE = "choice"  # 选择题
    TRUEFALSE = "truefalse"  # 判断题
    FILL = "fill"  # 填空题
    ESSAY = "essay"  # 问答题


class Difficulty(str, Enum):
    """难度等级枚举."""

    EASY = "easy"
    MEDIUM = "medium"
    HARD = "hard"


@dataclass
class BaseQuestion:
    """题目基类.

    Attributes
    ----------
    id (str): 题目唯一标识符
    type (QuestionType): 题目类型
    category (str): 题目分类
    difficulty (Difficulty): 难度等级
    question (str): 题目内容
    answer (str | bool | list): 正确答案
    explanation (str): 题目解析
    """

    id: str
    type: QuestionType
    category: str
    difficulty: Difficulty
    question: str
    answer: str | bool | list
    explanation: str = ""

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> BaseQuestion:
        """从字典创建题目对象.

        Parameters
        ----------
        data : dict[str, Any]
            题目数据字典

        Returns
        -------
        BaseQuestion
            题目对象
        """
        q_type = QuestionType(data.get("type", "choice"))
        difficulty = Difficulty(data.get("difficulty", "medium"))

        if q_type == QuestionType.CHOICE:
            return ChoiceQuestion.from_dict(data)
        if q_type == QuestionType.TRUEFALSE:
            return TrueFalseQuestion.from_dict(data)
        if q_type == QuestionType.FILL:
            return FillQuestion.from_dict(data)
        if q_type == QuestionType.ESSAY:
            return EssayQuestion.from_dict(data)
        return cls(
            id=data["id"],
            type=q_type,
            category=data.get("category", ""),
            difficulty=difficulty,
            question=data["question"],
            answer=data["answer"],
            explanation=data.get("explanation", ""),
        )

    def to_dict(self) -> dict[str, Any]:
        """转换为字典.

        Returns
        -------
        dict[str, Any]
            题目数据字典
        """
        return {
            "id": self.id,
            "type": self.type.value,
            "category": self.category,
            "difficulty": self.difficulty.value,
            "question": self.question,
            "answer": self.answer,
            "explanation": self.explanation,
        }

    def check_answer(self, user_answer: str | bool) -> bool:  # noqa: FBT001
        """检查用户答案是否正确.

        Parameters
        ----------
        user_answer : str | bool
            用户提交的答案

        Returns
        -------
        bool
            是否正确
        """
        if isinstance(self.answer, bool):
            return user_answer == self.answer
        if isinstance(self.answer, str):
            return str(user_answer).strip().lower() == str(self.answer).strip().lower()
        return str(user_answer).strip() in [str(a).strip() for a in self.answer]

    @property
    def type_display(self) -> str:
        """获取题目类型显示名称."""
        type_map = {
            QuestionType.CHOICE: "选择题",
            QuestionType.TRUEFALSE: "判断题",
            QuestionType.FILL: "填空题",
            QuestionType.ESSAY: "问答题",
        }
        return type_map.get(self.type, "未知")

    @property
    def difficulty_display(self) -> str:
        """获取难度等级显示名称."""
        difficulty_map = {
            Difficulty.EASY: "简单",
            Difficulty.MEDIUM: "中等",
            Difficulty.HARD: "困难",
        }
        return difficulty_map.get(self.difficulty, "未知")


@dataclass
class ChoiceQuestion(BaseQuestion):
    """选择题.

    Attributes
    ----------
    options (list[str]): 选项列表
    """

    options: list[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> ChoiceQuestion:
        """从字典创建选择题对象."""
        return cls(
            id=data["id"],
            type=QuestionType.CHOICE,
            category=data.get("category", ""),
            difficulty=Difficulty(data.get("difficulty", "medium")),
            question=data["question"],
            answer=data["answer"],
            explanation=data.get("explanation", ""),
            options=data.get("options", []),
        )

    def to_dict(self) -> dict[str, Any]:
        """转换为字典."""
        data = super().to_dict()
        data["options"] = self.options
        return data


@dataclass
class TrueFalseQuestion(BaseQuestion):
    """判断题."""

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> TrueFalseQuestion:
        """从字典创建判断题对象."""
        return cls(
            id=data["id"],
            type=QuestionType.TRUEFALSE,
            category=data.get("category", ""),
            difficulty=Difficulty(data.get("difficulty", "medium")),
            question=data["question"],
            answer=data["answer"],
            explanation=data.get("explanation", ""),
        )


@dataclass
class FillQuestion(BaseQuestion):
    """填空题."""

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> FillQuestion:
        """从字典创建填空题对象."""
        return cls(
            id=data["id"],
            type=QuestionType.FILL,
            category=data.get("category", ""),
            difficulty=Difficulty(data.get("difficulty", "medium")),
            question=data["question"],
            answer=data["answer"],
            explanation=data.get("explanation", ""),
        )


@dataclass
class EssayQuestion(BaseQuestion):
    """问答题."""

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> EssayQuestion:
        """从字典创建问答题对象."""
        return cls(
            id=data["id"],
            type=QuestionType.ESSAY,
            category=data.get("category", ""),
            difficulty=Difficulty(data.get("difficulty", "medium")),
            question=data["question"],
            answer=data["answer"],
            explanation=data.get("explanation", ""),
        )


@dataclass
class AnswerRecord:
    """答题记录.

    Attributes
    ----------
    question_id (str): 题目ID
    user_answer (str | bool): 用户答案
    is_correct (bool): 是否正确
    timestamp (str): 答题时间
    time_spent (int): 答题用时(秒)
    """

    question_id: str
    user_answer: str | bool
    is_correct: bool
    timestamp: str = field(default_factory=lambda: datetime.now(tz=timezone.utc).isoformat())
    time_spent: int = 0

    def to_dict(self) -> dict[str, Any]:
        """转换为字典."""
        return {
            "question_id": self.question_id,
            "user_answer": self.user_answer,
            "is_correct": self.is_correct,
            "timestamp": self.timestamp,
            "time_spent": self.time_spent,
        }

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> AnswerRecord:
        """从字典创建答题记录."""
        return cls(
            question_id=data["question_id"],
            user_answer=data["user_answer"],
            is_correct=data["is_correct"],
            timestamp=data.get("timestamp", ""),
            time_spent=data.get("time_spent", 0),
        )


@dataclass
class UserData:
    """用户数据.

    Attributes
    ----------
    user_id (str): 用户ID
    history (list[AnswerRecord]): 答题历史
    category_stats (dict[str, dict]): 分类统计
    """

    user_id: str = "default"
    history: list[AnswerRecord] = field(default_factory=list)
    category_stats: dict[str, dict[str, int]] = field(default_factory=dict)

    @property
    def total_questions(self) -> int:
        """总答题数."""
        return len(self.history)

    @property
    def correct_count(self) -> int:
        """正确答题数."""
        return sum(1 for r in self.history if r.is_correct)

    @property
    def accuracy(self) -> float:
        """正确率."""
        if self.total_questions == 0:
            return 0.0
        return round(self.correct_count / self.total_questions * 100, 1)

    def to_dict(self) -> dict[str, Any]:
        """转换为字典."""
        return {
            "user_id": self.user_id,
            "history": [r.to_dict() for r in self.history],
            "category_stats": self.category_stats,
            "total_questions": self.total_questions,
            "correct_count": self.correct_count,
            "accuracy": self.accuracy,
        }

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> UserData:
        """从字典创建用户数据."""
        return cls(
            user_id=data.get("user_id", "default"),
            history=[AnswerRecord.from_dict(r) for r in data.get("history", [])],
            category_stats=data.get("category_stats", {}),
        )


@dataclass
class QuizCategory:
    """题目分类.

    Attributes
    ----------
    name (str): 分类名称
    description (str): 分类描述
    question_count (int): 题目数量
    difficulty_dist (dict[str, int]): 难度分布
    """

    name: str
    description: str = ""
    question_count: int = 0
    difficulty_dist: dict[str, int] = field(default_factory=dict)
