"""EditTemplateVersion + 数据类 domain 模块单测."""

from __future__ import annotations

import pytest

from packages.domain.recipe import Recipe, RecipeItem
from packages.domain.template import Template, TemplateCategory, TemplateSegment
from packages.domain.template_version import EditTemplateVersion
from packages.domain.title_library import TitleLibraryItem
from packages.domain.voice_library import VoiceLibraryItem

# ── EditTemplateVersion ────────────────────────────────────────────────────


class TestEditTemplateVersion:
    def test_create_basic(self):
        v = EditTemplateVersion.create(template_id="t1", version=1)
        assert v.id
        assert v.template_id == "t1"
        assert v.version == 1
        assert v.name == ""
        assert v.editing_mode == "one_take"
        assert v.config == {}
        assert v.clip_configs == []
        assert v.change_note == ""
        assert v.published_by == ""

    def test_create_with_name(self):
        v = EditTemplateVersion.create(template_id="t1", version=1, name="v1.0 初版")
        assert v.name == "v1.0 初版"

    def test_create_with_editing_mode(self):
        v = EditTemplateVersion.create(template_id="t1", version=1, editing_mode="pip")
        assert v.editing_mode == "pip"

    def test_create_with_config(self):
        config = {"bgm": {"volume": 0.5}}
        v = EditTemplateVersion.create(template_id="t1", version=1, config=config)
        assert v.config == config

    def test_create_config_none_defaults_empty(self):
        v = EditTemplateVersion.create(template_id="t1", version=1, config=None)
        assert v.config == {}

    def test_create_with_clip_configs(self):
        clips = [{"type": "intro"}, {"type": "main"}]
        v = EditTemplateVersion.create(template_id="t1", version=1, clip_configs=clips)
        assert v.clip_configs == clips

    def test_create_clip_configs_none_defaults_empty(self):
        v = EditTemplateVersion.create(template_id="t1", version=1, clip_configs=None)
        assert v.clip_configs == []

    def test_create_with_change_note(self):
        v = EditTemplateVersion.create(
            template_id="t1",
            version=2,
            change_note="修复时长计算问题",
        )
        assert v.change_note == "修复时长计算问题"

    def test_create_with_published_by(self):
        v = EditTemplateVersion.create(template_id="t1", version=1, published_by="user1")
        assert v.published_by == "user1"

    def test_created_at_auto_set(self):
        v = EditTemplateVersion.create(template_id="t1", version=1)
        assert v.created_at is not None

    def test_unique_ids(self):
        v1 = EditTemplateVersion.create(template_id="t1", version=1)
        v2 = EditTemplateVersion.create(template_id="t1", version=2)
        assert v1.id != v2.id

    def test_version_integer(self):
        v = EditTemplateVersion.create(template_id="t1", version=5)
        assert v.version == 5


# ── Template / TemplateSegment / TemplateCategory ─────────────────────────


class TestTemplate:
    def test_template_defaults(self):
        t = Template(id="t1", user_id="u1", name="我的模板", mode="pip")
        assert t.id == "t1"
        assert t.user_id == "u1"
        assert t.name == "我的模板"
        assert t.mode == "pip"
        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
        assert t.created_at is not None
        assert t.updated_at is not None

    def test_template_with_segments(self):
        seg = TemplateSegment(
            id="s1",
            template_id="t1",
            segment_order=0,
            duration_min=2.0,
            duration_max=5.0,
        )
        t = Template(id="t1", user_id="u1", name="T1", mode="pip", segments=[seg])
        assert len(t.segments) == 1
        assert t.segments[0].id == "s1"

    def test_template_with_tags(self):
        t = Template(id="t1", user_id="u1", name="T1", mode="pip", tags=["旅行", "美食"])
        assert t.tags == ["旅行", "美食"]

    def test_template_segment_defaults(self):
        seg = TemplateSegment(
            id="s1",
            template_id="t1",
            segment_order=0,
            duration_min=1.0,
            duration_max=3.0,
        )
        assert seg.material_type is None
        assert seg.created_at is not None

    def test_template_segment_with_material_type(self):
        seg = TemplateSegment(
            id="s1",
            template_id="t1",
            segment_order=0,
            duration_min=1.0,
            duration_max=3.0,
            material_type="人物",
        )
        assert seg.material_type == "人物"

    def test_template_category(self):
        cat = TemplateCategory(id="c1", user_id="u1", name="旅行vlog")
        assert cat.id == "c1"
        assert cat.user_id == "u1"
        assert cat.name == "旅行vlog"
        assert cat.created_at is not None


# ── Recipe ─────────────────────────────────────────────────────────────────


class TestRecipe:
    def test_recipe_defaults(self):
        r = Recipe(id="r1", user_id="u1", name="一键旅行")
        assert r.id == "r1"
        assert r.user_id == "u1"
        assert r.name == "一键旅行"
        assert r.description == ""
        assert r.template_id == ""
        assert r.generation_params == {}
        assert r.items == []
        assert r.is_active is True
        assert r.metadata_ == {}
        assert r.created_at is not None
        assert r.updated_at is not None

    def test_recipe_with_items(self):
        item = RecipeItem(
            id="i1",
            recipe_id="r1",
            item_type="asset",
            item_id="asset_1",
            position=0,
        )
        r = Recipe(id="r1", user_id="u1", name="R1", items=[item])
        assert len(r.items) == 1
        assert r.items[0].item_type == "asset"

    def test_recipe_item_defaults(self):
        item = RecipeItem(id="i1", recipe_id="r1", item_type="title", item_id="t1")
        assert item.position == 0
        assert item.metadata_ == {}

    def test_recipe_item_with_metadata(self):
        item = RecipeItem(
            id="i1",
            recipe_id="r1",
            item_type="voice",
            item_id="v1",
            position=2,
            metadata_={"speed": 1.2},
        )
        assert item.position == 2
        assert item.metadata_ == {"speed": 1.2}


# ── TitleLibraryItem ───────────────────────────────────────────────────────


class TestTitleLibraryItem:
    def test_defaults(self):
        item = TitleLibraryItem(
            id="t1",
            user_id="u1",
            name="标题1",
            text="欢迎收看",
        )
        assert item.id == "t1"
        assert item.user_id == "u1"
        assert item.name == "标题1"
        assert item.text == "欢迎收看"
        assert item.category == "default"
        assert item.description == ""
        assert item.tags == []
        assert item.usage_count == 0
        assert item.is_active is True
        assert item.metadata_ == {}
        assert item.created_at is not None
        assert item.updated_at is not None

    def test_with_category(self):
        item = TitleLibraryItem(
            id="t1",
            user_id="u1",
            name="t1",
            text="txt",
            category="opening",
        )
        assert item.category == "opening"

    def test_with_tags(self):
        item = TitleLibraryItem(
            id="t1",
            user_id="u1",
            name="t1",
            text="txt",
            tags=["搞笑", "热门"],
        )
        assert item.tags == ["搞笑", "热门"]

    def test_with_usage_count(self):
        item = TitleLibraryItem(
            id="t1",
            user_id="u1",
            name="t1",
            text="txt",
            usage_count=42,
        )
        assert item.usage_count == 42


# ── VoiceLibraryItem ───────────────────────────────────────────────────────


class TestVoiceLibraryItem:
    def test_defaults(self):
        item = VoiceLibraryItem(
            id="v1",
            user_id="u1",
            name="温柔女声",
        )
        assert item.id == "v1"
        assert item.user_id == "u1"
        assert item.name == "温柔女声"
        assert item.text == ""
        assert item.voice_provider == ""
        assert item.voice_id == ""
        assert item.voice_name == ""
        assert item.audio_url == ""
        assert item.duration == 0
        assert item.file_size == 0
        assert item.status == "completed"
        assert item.project_id is None
        assert item.tags == []
        assert item.metadata_ == {}
        assert item.created_at is not None
        assert item.updated_at is not None

    def test_with_voice_info(self):
        item = VoiceLibraryItem(
            id="v1",
            user_id="u1",
            name="v1",
            voice_provider="cosyvoice",
            voice_id="voice_001",
            voice_name="小溪",
            audio_url="https://example.com/audio.mp3",
            duration=15.5,
            file_size=320000,
        )
        assert item.voice_provider == "cosyvoice"
        assert item.voice_id == "voice_001"
        assert item.voice_name == "小溪"
        assert item.duration == 15.5
        assert item.file_size == 320000

    def test_with_project_id(self):
        item = VoiceLibraryItem(
            id="v1",
            user_id="u1",
            name="v1",
            project_id="proj_123",
        )
        assert item.project_id == "proj_123"

    def test_with_tags(self):
        item = VoiceLibraryItem(
            id="v1",
            user_id="u1",
            name="v1",
            tags=["温柔", "女声"],
        )
        assert item.tags == ["温柔", "女声"]
