"""transition_presets 模块单元测试."""

from dataclasses import FrozenInstanceError

import pytest
from domain.transition_presets import (
    TRANSITION_PRESET_LIBRARY,
    TransitionPreset,
    get_default_transition,
    get_transition_preset,
    list_transition_presets,
)


class TestTransitionPreset:
    """TransitionPreset 数据类测试."""

    def test_create_required_fields(self):
        t = TransitionPreset(id="test_001", name="测试转场", category="basic")
        assert t.id == "test_001"
        assert t.name == "测试转场"
        assert t.category == "basic"
        # 默认值
        assert t.description == ""
        assert t.tags == []
        assert t.transition == "fade"
        assert t.default_duration == 0.5
        assert t.min_duration == 0.1
        assert t.max_duration == 3.0
        assert t.has_custom_params is False

    def test_create_all_fields(self):
        t = TransitionPreset(
            id="test_002",
            name="完整转场",
            category="slide",
            description="测试描述",
            tags=["标签1", "标签2"],
            transition="slideleft",
            default_duration=1.0,
            min_duration=0.3,
            max_duration=2.5,
            has_custom_params=True,
        )
        assert t.category == "slide"
        assert t.description == "测试描述"
        assert t.tags == ["标签1", "标签2"]
        assert t.transition == "slideleft"
        assert t.default_duration == 1.0
        assert t.min_duration == 0.3
        assert t.max_duration == 2.5
        assert t.has_custom_params is True

    def test_frozen_immutable(self):
        t = TransitionPreset(id="test", name="测试", category="basic")
        with pytest.raises(FrozenInstanceError):
            t.name = "修改"  # type: ignore[misc]

    def test_tags_default_new_list(self):
        t1 = TransitionPreset(id="1", name="a", category="basic")
        t2 = TransitionPreset(id="2", name="b", category="basic")
        assert t1.tags is not t2.tags
        assert t1.tags == []


class TestTransitionPresetLibrary:
    """TRANSITION_PRESET_LIBRARY 预设库测试."""

    def test_not_empty(self):
        assert len(TRANSITION_PRESET_LIBRARY) > 0

    def test_all_unique_ids(self):
        ids = [t.id for t in TRANSITION_PRESET_LIBRARY]
        assert len(ids) == len(set(ids)), "转场 ID 不能重复"

    def test_all_are_transition_preset_instances(self):
        for t in TRANSITION_PRESET_LIBRARY:
            assert isinstance(t, TransitionPreset)

    def test_contains_basic_categories(self):
        cats = {t.category for t in TRANSITION_PRESET_LIBRARY}
        assert "basic" in cats
        assert "fade" in cats

    def test_duration_constraints_valid(self):
        """每个预设的 min <= default <= max."""
        for t in TRANSITION_PRESET_LIBRARY:
            assert t.min_duration <= t.default_duration, f"{t.id}: min > default"
            assert t.default_duration <= t.max_duration, f"{t.id}: default > max"

    def test_none_transition_zero_duration(self):
        t = get_transition_preset("transition_none")
        assert t is not None
        assert t.default_duration == 0.0
        assert t.min_duration == 0.0
        assert t.max_duration == 0.0


class TestGetTransitionPreset:
    """get_transition_preset 函数测试."""

    def test_existing_id(self):
        t = get_transition_preset("transition_fade")
        assert t is not None
        assert t.id == "transition_fade"
        assert t.name == "淡入淡出"
        assert t.category == "fade"

    def test_nonexistent_id(self):
        assert get_transition_preset("nonexistent") is None

    def test_empty_string(self):
        assert get_transition_preset("") is None


class TestListTransitionPresets:
    """list_transition_presets 函数测试."""

    def test_no_filters_returns_all(self):
        result = list_transition_presets()
        assert len(result) == len(TRANSITION_PRESET_LIBRARY)

    def test_filter_by_category_basic(self):
        result = list_transition_presets(category="basic")
        assert len(result) >= 2
        for t in result:
            assert t.category == "basic"

    def test_filter_by_category_fade(self):
        result = list_transition_presets(category="fade")
        assert len(result) >= 3
        for t in result:
            assert t.category == "fade"

    def test_filter_by_unknown_category_returns_empty(self):
        result = list_transition_presets(category="nonexistent")
        assert result == []

    def test_filter_by_keyword_name(self):
        result = list_transition_presets(keyword="淡入")
        assert len(result) >= 1
        assert any(t.name == "淡入淡出" for t in result)

    def test_filter_by_keyword_description(self):
        result = list_transition_presets(keyword="经典")
        assert len(result) >= 1

    def test_filter_by_keyword_tag(self):
        result = list_transition_presets(keyword="电影感")
        assert len(result) >= 1

    def test_filter_keyword_case_insensitive(self):
        r1 = list_transition_presets(keyword="FADE")
        r2 = list_transition_presets(keyword="fade")
        assert len(r1) == len(r2)

    def test_filter_keyword_no_match(self):
        result = list_transition_presets(keyword="xyz_nonexistent_12345")
        assert result == []

    def test_combined_category_and_keyword(self):
        result = list_transition_presets(category="fade", keyword="黑场")
        assert len(result) >= 1
        for t in result:
            assert t.category == "fade"

    def test_combined_no_match(self):
        result = list_transition_presets(category="basic", keyword="黑场")
        assert result == []


class TestGetDefaultTransition:
    """get_default_transition 函数测试."""

    def test_returns_none_transition(self):
        t = get_default_transition()
        assert t.id == "transition_none"
        assert t.name == "无转场"

    def test_returns_transition_preset_instance(self):
        assert isinstance(get_default_transition(), TransitionPreset)
