"""
Template 模板领域模型单元测试
"""

from domain.template import Template, TemplateCategory, TemplateSegment


class TestTemplateSegment:
    """TemplateSegment 测试"""

    def test_create_segment(self):
        seg = TemplateSegment(
            id="seg-1",
            template_id="tpl-1",
            segment_order=1,
            duration_min=3.0,
            duration_max=5.0,
        )
        assert seg.id == "seg-1"
        assert seg.template_id == "tpl-1"
        assert seg.segment_order == 1
        assert seg.duration_min == 3.0
        assert seg.duration_max == 5.0
        assert seg.material_type is None

    def test_segment_with_material_type(self):
        seg = TemplateSegment(
            id="seg-1",
            template_id="tpl-1",
            segment_order=0,
            duration_min=2.0,
            duration_max=4.0,
            material_type="人物",
        )
        assert seg.material_type == "人物"

    def test_segment_has_timestamps(self):
        seg = TemplateSegment(
            id="seg-1",
            template_id="tpl-1",
            segment_order=1,
            duration_min=1.0,
            duration_max=2.0,
        )
        assert seg.created_at is not None
        assert seg.updated_at is not None


class TestTemplate:
    """Template 测试"""

    def test_create_template_minimal(self):
        t = Template(
            id="tpl-1",
            user_id="user-1",
            name="测试模板",
            mode="one_take",
        )
        assert t.id == "tpl-1"
        assert t.user_id == "user-1"
        assert t.name == "测试模板"
        assert t.mode == "one_take"

    def test_default_values(self):
        t = Template(id="tpl-1", user_id="u1", name="n", mode="one_take")
        assert t.category == ""
        assert t.tags == []
        assert t.title_config == {}
        assert t.subtitle_config == {}
        assert t.bgm_config == {}
        assert t.estimated_duration == 0.0
        assert t.segments == []
        assert t.is_active is True

    def test_with_segments(self):
        segs = [
            TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=2, duration_max=4),
            TemplateSegment(id="s2", template_id="t1", segment_order=1, duration_min=3, duration_max=5),
        ]
        t = Template(
            id="tpl-1",
            user_id="u1",
            name="n",
            mode="voice_over",
            segments=segs,
        )
        assert len(t.segments) == 2
        assert t.segments[0].segment_order == 0
        assert t.segments[1].segment_order == 1

    def test_all_modes(self):
        for mode in ["pip", "voice_pip", "one_take", "voice_over"]:
            t = Template(id="t1", user_id="u1", name="n", mode=mode)
            assert t.mode == mode

    def test_with_configs(self):
        t = Template(
            id="t1",
            user_id="u1",
            name="n",
            mode="one_take",
            title_config={"font_size": 24, "color": "#ffffff"},
            subtitle_config={"style": "bottom"},
            bgm_config={"volume": 0.5},
        )
        assert t.title_config["font_size"] == 24
        assert t.subtitle_config["style"] == "bottom"
        assert t.bgm_config["volume"] == 0.5

    def test_estimated_duration(self):
        t = Template(
            id="t1",
            user_id="u1",
            name="n",
            mode="one_take",
            estimated_duration=30.5,
        )
        assert t.estimated_duration == 30.5

    def test_is_active_false(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", is_active=False)
        assert t.is_active is False

    def test_has_timestamps(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take")
        assert t.created_at is not None
        assert t.updated_at is not None

    def test_tags_list(self):
        t = Template(
            id="t1",
            user_id="u1",
            name="n",
            mode="one_take",
            tags=["风景", "vlog"],
        )
        assert "风景" in t.tags
        assert "vlog" in t.tags
        assert len(t.tags) == 2


class TestTemplateCategory:
    """TemplateCategory 测试"""

    def test_create_category(self):
        cat = TemplateCategory(id="cat-1", user_id="u1", name="风景")
        assert cat.id == "cat-1"
        assert cat.user_id == "u1"
        assert cat.name == "风景"

    def test_category_has_timestamp(self):
        cat = TemplateCategory(id="cat-1", user_id="u1", name="风景")
        assert cat.created_at is not None


class TestTemplateExtended:
    """Template 深度补充测试"""

    def test_tags_independence(self):
        """不同模板的 tags 列表互不影响"""
        t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take")
        t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take")
        t1.tags.append("新标签")
        assert "新标签" not in t2.tags
        assert len(t2.tags) == 0

    def test_title_config_independence(self):
        t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take")
        t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take")
        t1.title_config["key"] = "val"
        assert "key" not in t2.title_config

    def test_subtitle_config_independence(self):
        t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take")
        t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take")
        t1.subtitle_config["key"] = "val"
        assert "key" not in t2.subtitle_config

    def test_bgm_config_independence(self):
        t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take")
        t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take")
        t1.bgm_config["key"] = "val"
        assert "key" not in t2.bgm_config

    def test_segments_independence(self):
        segs = [
            TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=2),
        ]
        t1 = Template(id="t1", user_id="u1", name="n1", mode="one_take", segments=segs)
        t2 = Template(id="t2", user_id="u1", name="n2", mode="one_take")
        assert len(t2.segments) == 0

    def test_empty_segments(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", segments=[])
        assert t.segments == []

    def test_many_segments(self):
        segs = [
            TemplateSegment(id=f"s{i}", template_id="t1", segment_order=i, duration_min=1, duration_max=3)
            for i in range(30)
        ]
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", segments=segs)
        assert len(t.segments) == 30
        assert t.segments[0].segment_order == 0
        assert t.segments[29].segment_order == 29

    def test_zero_estimated_duration(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", estimated_duration=0.0)
        assert t.estimated_duration == 0.0

    def test_negative_estimated_duration(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", estimated_duration=-1.0)
        assert t.estimated_duration == -1.0

    def test_large_estimated_duration(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", estimated_duration=9999.9)
        assert t.estimated_duration == 9999.9

    def test_empty_category(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", category="")
        assert t.category == ""

    def test_custom_category(self):
        t = Template(id="t1", user_id="u1", name="n", mode="one_take", category="美食探店")
        assert t.category == "美食探店"

    def test_empty_name(self):
        t = Template(id="t1", user_id="u1", name="", mode="one_take")
        assert t.name == ""

    def test_unicode_name(self):
        t = Template(id="t1", user_id="u1", name="🎬 美食探店 · Vlog模板", mode="one_take")
        assert "🎬" in t.name
        assert "美食探店" in t.name

    def test_special_characters_in_name(self):
        special = "模!@#$%板"
        t = Template(id="t1", user_id="u1", name=special, mode="one_take")
        assert t.name == special

    def test_long_name(self):
        long_name = "模板" * 100
        t = Template(id="t1", user_id="u1", name=long_name, mode="one_take")
        assert t.name == long_name
        assert len(t.name) == 200


class TestTemplateSegmentExtended:
    """TemplateSegment 深度补充测试"""

    def test_zero_duration(self):
        seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=0, duration_max=0)
        assert seg.duration_min == 0
        assert seg.duration_max == 0

    def test_negative_duration_min(self):
        seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=-1, duration_max=5)
        assert seg.duration_min == -1

    def test_negative_duration_max(self):
        seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=-5)
        assert seg.duration_max == -5

    def test_large_duration(self):
        seg = TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=0, duration_max=9999.9)
        assert seg.duration_max == 9999.9

    def test_negative_order(self):
        seg = TemplateSegment(id="s1", template_id="t1", segment_order=-5, duration_min=1, duration_max=3)
        assert seg.segment_order == -5

    def test_large_order(self):
        seg = TemplateSegment(id="s1", template_id="t1", segment_order=999, duration_min=1, duration_max=3)
        assert seg.segment_order == 999

    def test_material_type_none(self):
        seg = TemplateSegment(
            id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=3, material_type=None
        )
        assert seg.material_type is None

    def test_material_type_empty_string(self):
        seg = TemplateSegment(
            id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=3, material_type=""
        )
        assert seg.material_type == ""

    def test_material_type_unicode(self):
        seg = TemplateSegment(
            id="s1", template_id="t1", segment_order=0, duration_min=1, duration_max=3, material_type="风景"
        )
        assert seg.material_type == "风景"
