"""generated_video 领域模型单元测试."""

import pytest
from domain.generated_video import GeneratedVideo


class TestGeneratedVideoCreate:
    """GeneratedVideo.create 工厂方法测试."""

    def test_create_with_required_fields(self):
        video = GeneratedVideo.create(
            project_id="proj_001",
            generation_task_id="task_001",
            name="测试视频",
            file_url="https://example.com/out.mp4",
        )
        assert video.id
        assert len(video.id) == 32
        assert video.project_id == "proj_001"
        assert video.generation_task_id == "task_001"
        assert video.name == "测试视频"
        assert video.file_url == "https://example.com/out.mp4"
        # 默认值
        assert video.user_id == ""
        assert video.file_size == 0
        assert video.duration == 0.0
        assert video.width == 0
        assert video.height == 0
        assert video.fps == 0.0
        assert video.thumbnail_url is None
        assert video.status == "completed"
        assert video.review_status == "pending_review"
        assert video.generation_params == {}
        assert video.video_fingerprint is None
        assert video.is_duplicate is False
        assert video.duplicate_of is None
        assert video.generated_at is not None
        assert video.created_at is not None

    def test_create_with_all_fields(self):
        video = GeneratedVideo.create(
            project_id="proj_002",
            generation_task_id="task_002",
            name="完整视频",
            file_url="https://example.com/full.mp4",
            user_id="user_001",
            file_size=1024000,
            duration=30.5,
            width=1920,
            height=1080,
            fps=30.0,
            thumbnail_url="https://example.com/thumb.jpg",
            generation_params={"quality": "high"},
        )
        assert video.user_id == "user_001"
        assert video.file_size == 1024000
        assert video.duration == 30.5
        assert video.width == 1920
        assert video.height == 1080
        assert video.fps == 30.0
        assert video.thumbnail_url == "https://example.com/thumb.jpg"
        assert video.generation_params == {"quality": "high"}

    def test_create_strips_strings(self):
        video = GeneratedVideo.create(
            project_id="  proj_003  ",
            generation_task_id="  task_003  ",
            name="  测试视频  ",
            file_url="  https://example.com/out.mp4  ",
            user_id="  user_003  ",
        )
        assert video.project_id == "proj_003"
        assert video.generation_task_id == "task_003"
        assert video.name == "测试视频"
        assert video.file_url == "https://example.com/out.mp4"
        assert video.user_id == "user_003"

    def test_create_empty_project_id_raises(self):
        with pytest.raises(ValueError, match="project_id"):
            GeneratedVideo.create(
                project_id="",
                generation_task_id="t",
                name="n",
                file_url="u",
            )

    def test_create_whitespace_project_id_raises(self):
        with pytest.raises(ValueError, match="project_id"):
            GeneratedVideo.create(
                project_id="   ",
                generation_task_id="t",
                name="n",
                file_url="u",
            )

    def test_create_empty_generation_task_id_raises(self):
        with pytest.raises(ValueError, match="generation_task_id"):
            GeneratedVideo.create(
                project_id="p",
                generation_task_id="",
                name="n",
                file_url="u",
            )

    def test_create_empty_name_raises(self):
        with pytest.raises(ValueError, match="name"):
            GeneratedVideo.create(
                project_id="p",
                generation_task_id="t",
                name="",
                file_url="u",
            )

    def test_create_empty_file_url_raises(self):
        with pytest.raises(ValueError, match="file_url"):
            GeneratedVideo.create(
                project_id="p",
                generation_task_id="t",
                name="n",
                file_url="",
            )

    def test_create_none_generation_params_defaults_to_empty_dict(self):
        video = GeneratedVideo.create(
            project_id="p",
            generation_task_id="t",
            name="n",
            file_url="u",
            generation_params=None,
        )
        assert video.generation_params == {}

    def test_create_ids_are_unique(self):
        v1 = GeneratedVideo.create(project_id="p", generation_task_id="t1", name="n1", file_url="u1")
        v2 = GeneratedVideo.create(project_id="p", generation_task_id="t2", name="n2", file_url="u2")
        assert v1.id != v2.id

    def test_create_timestamps_are_utc(self):
        video = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u")
        assert video.created_at.tzinfo is not None
        assert video.generated_at.tzinfo is not None


class TestGeneratedVideoProperties:
    """GeneratedVideo 属性测试"""

    def test_default_status_completed(self):
        gv = GeneratedVideo.create(
            project_id="proj-1",
            generation_task_id="task-1",
            name="测试视频",
            file_url="https://example.com/video.mp4",
        )
        assert gv.status == "completed"

    def test_default_review_status(self):
        gv = GeneratedVideo.create(
            project_id="proj-1",
            generation_task_id="task-1",
            name="测试视频",
            file_url="https://example.com/video.mp4",
        )
        assert gv.review_status == "pending_review"

    def test_set_status(self):
        gv = GeneratedVideo.create(
            project_id="proj-1",
            generation_task_id="task-1",
            name="测试视频",
            file_url="https://example.com/video.mp4",
        )
        gv.status = "failed"
        assert gv.status == "failed"

    def test_mark_as_duplicate(self):
        gv = GeneratedVideo.create(
            project_id="proj-1",
            generation_task_id="task-1",
            name="测试视频",
            file_url="https://example.com/video.mp4",
        )
        gv.is_duplicate = True
        gv.duplicate_of = "video-original"
        assert gv.is_duplicate is True
        assert gv.duplicate_of == "video-original"

    def test_set_fingerprint(self):
        gv = GeneratedVideo.create(
            project_id="proj-1",
            generation_task_id="task-1",
            name="测试视频",
            file_url="https://example.com/video.mp4",
        )
        fingerprint = {"phash": "abc123", "md5": "def456"}
        gv.video_fingerprint = fingerprint
        assert gv.video_fingerprint == fingerprint


class TestGeneratedVideoExtended:
    """GeneratedVideo 深度补充测试"""

    def test_id_is_hex(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u")
        int(v.id, 16)

    def test_zero_file_size(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", file_size=0)
        assert v.file_size == 0

    def test_large_file_size(self):
        large = 1024 * 1024 * 1024  # 1GB
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", file_size=large)
        assert v.file_size == large

    def test_zero_duration(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", duration=0.0)
        assert v.duration == 0.0

    def test_large_duration(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", duration=9999.99)
        assert v.duration == 9999.99

    def test_zero_dimensions(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", width=0, height=0)
        assert v.width == 0
        assert v.height == 0

    def test_4k_dimensions(self):
        v = GeneratedVideo.create(
            project_id="p", generation_task_id="t", name="n", file_url="u", width=3840, height=2160
        )
        assert v.width == 3840
        assert v.height == 2160

    def test_zero_fps(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", fps=0.0)
        assert v.fps == 0.0

    def test_high_fps(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", fps=120.0)
        assert v.fps == 120.0

    def test_empty_user_id(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", user_id="")
        assert v.user_id == ""

    def test_long_name(self):
        long_name = "视频" * 100
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name=long_name, file_url="u")
        assert v.name == long_name
        assert len(v.name) == 200

    def test_unicode_name(self):
        v = GeneratedVideo.create(
            project_id="p", generation_task_id="t", name="🎬 我的精彩视频 · 旅行vlog", file_url="u"
        )
        assert "🎬" in v.name
        assert "旅行vlog" in v.name

    def test_special_characters_name(self):
        special = "视!@#$%^&*()频"
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name=special, file_url="u")
        assert v.name == special

    def test_thumbnail_url_none(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u", thumbnail_url=None)
        assert v.thumbnail_url is None

    def test_generation_params_complex(self):
        params = {
            "mode": "voice_over",
            "quality": "high",
            "resolution": {"width": 1920, "height": 1080},
            "effects": ["filter", "transition"],
        }
        v = GeneratedVideo.create(
            project_id="p", generation_task_id="t", name="n", file_url="u", generation_params=params
        )
        assert v.generation_params["mode"] == "voice_over"
        assert v.generation_params["resolution"]["width"] == 1920
        assert len(v.generation_params["effects"]) == 2

    def test_generation_params_independence(self):
        v1 = GeneratedVideo.create(project_id="p", generation_task_id="t1", name="n1", file_url="u1")
        v2 = GeneratedVideo.create(project_id="p", generation_task_id="t2", name="n2", file_url="u2")
        v1.generation_params["key"] = "val"
        assert "key" not in v2.generation_params

    def test_status_failed(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u")
        v.status = "failed"
        assert v.status == "failed"

    def test_review_status_approved(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u")
        v.review_status = "approved"
        assert v.review_status == "approved"

    def test_is_duplicate_default_false(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u")
        assert v.is_duplicate is False
        assert v.duplicate_of is None

    def test_fingerprint_none_default(self):
        v = GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="u")
        assert v.video_fingerprint is None

    def test_empty_file_url_raises(self):
        with pytest.raises(ValueError):
            GeneratedVideo.create(project_id="p", generation_task_id="t", name="n", file_url="  ")
