"""QuizTrainer 模型测试."""

import sys
from pathlib import Path

# 添加项目路径
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "pytola-office"))

import pytest

from pytola_office.quiztrainer.models import (
    AnswerRecord,
    ChoiceQuestion,
    Difficulty,
    EssayQuestion,
    FillQuestion,
    QuestionType,
    QuizCategory,
    TrueFalseQuestion,
    UserData,
)


class TestQuestionType:
    """题目类型测试."""

    def test_question_types(self) -> None:
        """测试题目类型枚举."""
        assert QuestionType.CHOICE.value == "choice"
        assert QuestionType.TRUEFALSE.value == "truefalse"
        assert QuestionType.FILL.value == "fill"
        assert QuestionType.ESSAY.value == "essay"

    def test_difficulty_levels(self) -> None:
        """测试难度等级枚举."""
        assert Difficulty.EASY.value == "easy"
        assert Difficulty.MEDIUM.value == "medium"
        assert Difficulty.HARD.value == "hard"


class TestChoiceQuestion:
    """选择题测试."""

    def test_create_choice_question(self) -> None:
        """测试创建选择题."""
        q = ChoiceQuestion(
            id="q001",
            type=QuestionType.CHOICE,
            category="Python基础",
            difficulty=Difficulty.EASY,
            question="以下哪个是Python的列表?",
            answer="B",
            options=["A. {}", "B. []", "C. ()", "D. <>"],
            explanation="列表使用方括号",
        )
        assert q.id == "q001"
        assert q.type == QuestionType.CHOICE
        assert q.answer == "B"
        assert len(q.options) == 4

    def test_choice_question_from_dict(self) -> None:
        """测试从字典创建选择题."""
        data = {
            "id": "q002",
            "type": "choice",
            "category": "数据结构",
            "difficulty": "medium",
            "question": "字典使用什么符号?",
            "answer": "A",
            "options": ["A. {}", "B. []", "C. ()", "D. <>"],
            "explanation": "字典使用大括号",
        }
        q = ChoiceQuestion.from_dict(data)
        assert q.id == "q002"
        assert q.type == QuestionType.CHOICE
        assert q.answer == "A"

    def test_check_answer_correct(self) -> None:
        """测试正确答案判断."""
        q = ChoiceQuestion(
            id="q003",
            type=QuestionType.CHOICE,
            category="测试",
            difficulty=Difficulty.EASY,
            question="测试",
            answer="B",
            options=["A", "B", "C", "D"],
        )
        assert q.check_answer("B") is True
        assert q.check_answer("b") is True

    def test_check_answer_wrong(self) -> None:
        """测试错误答案判断."""
        q = ChoiceQuestion(
            id="q004",
            type=QuestionType.CHOICE,
            category="测试",
            difficulty=Difficulty.EASY,
            question="测试",
            answer="C",
            options=["A", "B", "C", "D"],
        )
        assert q.check_answer("A") is False

    def test_to_dict(self) -> None:
        """测试转换为字典."""
        q = ChoiceQuestion(
            id="q005",
            type=QuestionType.CHOICE,
            category="测试",
            difficulty=Difficulty.MEDIUM,
            question="测试题目",
            answer="D",
            options=["A", "B", "C", "D"],
            explanation="测试解析",
        )
        data = q.to_dict()
        assert data["id"] == "q005"
        assert data["type"] == "choice"
        assert data["answer"] == "D"
        assert len(data["options"]) == 4


class TestTrueFalseQuestion:
    """判断题测试."""

    def test_create_truefalse_question(self) -> None:
        """测试创建判断题."""
        q = TrueFalseQuestion(
            id="tf001",
            type=QuestionType.TRUEFALSE,
            category="Python基础",
            difficulty=Difficulty.EASY,
            question="Python是一种编译型语言",
            answer=False,
            explanation="Python是解释型语言",
        )
        assert q.id == "tf001"
        assert q.answer is False

    def test_truefalse_from_dict(self) -> None:
        """测试从字典创建判断题."""
        data = {
            "id": "tf002",
            "type": "truefalse",
            "category": "测试",
            "difficulty": "easy",
            "question": "这是判断题吗?",
            "answer": True,
            "explanation": "这是判断题",
        }
        q = TrueFalseQuestion.from_dict(data)
        assert q.answer is True

    def test_check_truefalse_answer(self) -> None:
        """测试判断题答案判断."""
        q = TrueFalseQuestion(
            id="tf003",
            type=QuestionType.TRUEFALSE,
            category="测试",
            difficulty=Difficulty.EASY,
            question="测试",
            answer=True,
        )
        assert q.check_answer(True) is True  # noqa: FBT003
        assert q.check_answer(False) is False  # noqa: FBT003


class TestFillQuestion:
    """填空题测试."""

    def test_create_fill_question(self) -> None:
        """测试创建填空题."""
        q = FillQuestion(
            id="fill001",
            type=QuestionType.FILL,
            category="Python基础",
            difficulty=Difficulty.MEDIUM,
            question="Python输出函数是___()",
            answer="print",
            explanation="print是输出函数",
        )
        assert q.id == "fill001"
        assert q.answer == "print"

    def test_fill_answer_case_insensitive(self) -> None:
        """测试填空题答案大小写不敏感."""
        q = FillQuestion(
            id="fill002",
            type=QuestionType.FILL,
            category="测试",
            difficulty=Difficulty.EASY,
            question="测试",
            answer="Python",
        )
        assert q.check_answer("python") is True
        assert q.check_answer("PYTHON") is True
        assert q.check_answer("Python") is True


class TestEssayQuestion:
    """问答题测试."""

    def test_create_essay_question(self) -> None:
        """测试创建问答题."""
        q = EssayQuestion(
            id="essay001",
            type=QuestionType.ESSAY,
            category="Python基础",
            difficulty=Difficulty.HARD,
            question="请简述Python的特点",
            answer="Python是一种高级编程语言...",
            explanation="参考答案要点",
        )
        assert q.id == "essay001"
        assert q.type == QuestionType.ESSAY
        assert q.difficulty == Difficulty.HARD


class TestAnswerRecord:
    """答题记录测试."""

    def test_create_answer_record(self) -> None:
        """测试创建答题记录."""
        record = AnswerRecord(
            question_id="q001",
            user_answer="B",
            is_correct=True,
            time_spent=30,
        )
        assert record.question_id == "q001"
        assert record.user_answer == "B"
        assert record.is_correct is True
        assert record.time_spent == 30

    def test_answer_record_to_dict(self) -> None:
        """测试答题记录转字典."""
        record = AnswerRecord(
            question_id="q002",
            user_answer="A",
            is_correct=False,
        )
        data = record.to_dict()
        assert data["question_id"] == "q002"
        assert data["user_answer"] == "A"
        assert data["is_correct"] is False

    def test_answer_record_from_dict(self) -> None:
        """测试从字典创建答题记录."""
        data = {
            "question_id": "q003",
            "user_answer": "C",
            "is_correct": True,
            "timestamp": "2024-01-15T10:30:00",
            "time_spent": 45,
        }
        record = AnswerRecord.from_dict(data)
        assert record.question_id == "q003"
        assert record.user_answer == "C"
        assert record.is_correct is True


class TestUserData:
    """用户数据测试."""

    def test_create_user_data(self) -> None:
        """测试创建用户数据."""
        user_data = UserData(user_id="test_user")
        assert user_data.user_id == "test_user"
        assert user_data.total_questions == 0
        assert user_data.correct_count == 0
        assert user_data.accuracy == pytest.approx(0.0, rel=0.1)

    def test_user_data_statistics(self) -> None:
        """测试用户数据统计."""
        user_data = UserData(user_id="test_user")
        user_data.history = [
            AnswerRecord(question_id="q1", user_answer="A", is_correct=True),
            AnswerRecord(question_id="q2", user_answer="B", is_correct=True),
            AnswerRecord(question_id="q3", user_answer="C", is_correct=False),
        ]
        assert user_data.total_questions == 3
        assert user_data.correct_count == 2
        assert user_data.accuracy == pytest.approx(66.7, rel=0.1)

    def test_user_data_empty_accuracy(self) -> None:
        """测试空数据的正确率."""
        user_data = UserData()
        assert user_data.accuracy == pytest.approx(0.0, rel=0.1)

    def test_user_data_to_dict(self) -> None:
        """测试用户数据转字典."""
        user_data = UserData(user_id="test")
        user_data.history = [
            AnswerRecord(question_id="q1", user_answer="A", is_correct=True),
        ]
        data = user_data.to_dict()
        assert data["user_id"] == "test"
        assert data["total_questions"] == 1
        assert data["correct_count"] == 1
        assert data["accuracy"] == pytest.approx(100.0, rel=0.1)


class TestQuizCategory:
    """题目分类测试."""

    def test_create_category(self) -> None:
        """测试创建分类."""
        category = QuizCategory(
            name="Python基础",
            description="Python基础知识",
            question_count=50,
            difficulty_dist={"easy": 20, "medium": 25, "hard": 5},
        )
        assert category.name == "Python基础"
        assert category.question_count == 50
        assert category.difficulty_dist["easy"] == 20


class TestTypeDisplay:
    """类型显示测试."""

    def test_question_type_display(self) -> None:
        """测试题目类型显示名称."""
        q = ChoiceQuestion(
            id="q1",
            type=QuestionType.CHOICE,
            category="测试",
            difficulty=Difficulty.EASY,
            question="测试",
            answer="A",
        )
        assert q.type_display == "选择题"

        tf = TrueFalseQuestion(
            id="tf1",
            type=QuestionType.TRUEFALSE,
            category="测试",
            difficulty=Difficulty.EASY,
            question="测试",
            answer=True,
        )
        assert tf.type_display == "判断题"

    def test_difficulty_display(self) -> None:
        """测试难度显示名称."""
        q = ChoiceQuestion(
            id="q1",
            type=QuestionType.CHOICE,
            category="测试",
            difficulty=Difficulty.HARD,
            question="测试",
            answer="A",
        )
        assert q.difficulty_display == "困难"


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
