"""#1660 成品视频 API 查重字段透传测试。

覆盖两套响应构造路径：
- routes/videos.py::_to_video_response        -> VideoItemResponse (/videos 列表)
- routes/generation_tasks.py::_to_generated_video_response -> GeneratedVideoResponse
"""

from types import SimpleNamespace
from unittest.mock import MagicMock

from app.api.routes.generation_tasks import _to_generated_video_response
from app.api.routes.videos import _to_video_response
from app.schemas.generated_video import GeneratedVideoResponse
from app.schemas.video_center import VideoItemResponse


def _make_item(**overrides):
    base = dict(
        id="v1",
        project_id="p1",
        generation_task_id="t1",
        name="成片",
        file_url="oss://bucket/v1.mp4",
        file_size=1024,
        duration=12.5,
        thumbnail_url=None,
        width=1080,
        height=1920,
        fps=30.0,
        status="completed",
        review_status="pending_review",
        generation_params={},
        generated_at=None,
        duplicate_rate=None,
        match_count=None,
        visual_similarity=None,
    )
    base.update(overrides)
    return SimpleNamespace(**base)


class TestVideoItemResponseDupFields:
    def test_passes_through_all_three_fields(self):
        item = _make_item(duplicate_rate=42.5, match_count=7, visual_similarity=0.83)
        resp = _to_video_response(item, storage=None)
        assert isinstance(resp, VideoItemResponse)
        assert resp.duplicate_rate == 42.5
        assert resp.match_count == 7
        assert resp.visual_similarity == 0.83

    def test_legacy_video_without_fields_returns_none(self):
        """老数据/实体无查重字段时保持 None（前端自动隐藏），不报错。"""
        item = SimpleNamespace(
            id="v2",
            project_id="p1",
            generation_task_id="t2",
            name="老视频",
            file_url="oss://bucket/v2.mp4",
            file_size=1,
            duration=1.0,
            thumbnail_url=None,
            width=720,
            height=1280,
            fps=24.0,
            status="completed",
            review_status="pending_review",
            generation_params={},
        )
        resp = _to_video_response(item, storage=None)
        assert resp.duplicate_rate is None
        assert resp.match_count is None
        assert resp.visual_similarity is None

    def test_explicit_none_values_kept(self):
        item = _make_item()
        resp = _to_video_response(item, storage=None)
        assert resp.duplicate_rate is None
        assert resp.match_count is None
        assert resp.visual_similarity is None

    def test_zero_match_count_is_valid_value(self):
        """计算后确无匹配：match_count=0 / visual_similarity=0.0 是合法值，不能变 None。"""
        item = _make_item(duplicate_rate=0.0, match_count=0, visual_similarity=0.0)
        resp = _to_video_response(item, storage=None)
        assert resp.match_count == 0
        assert resp.visual_similarity == 0.0


class TestGeneratedVideoResponseDupFields:
    def test_passes_through_all_three_fields(self):
        item = _make_item(duplicate_rate=15.2, match_count=3, visual_similarity=0.61)
        resp = _to_generated_video_response(item, download_url="https://dl/x")
        assert isinstance(resp, GeneratedVideoResponse)
        assert resp.duplicate_rate == 15.2
        assert resp.match_count == 3
        assert resp.visual_similarity == 0.61
        assert resp.download_url == "https://dl/x"

    def test_missing_fields_default_none(self):
        item = SimpleNamespace(
            id="v3",
            project_id="p1",
            generation_task_id="t3",
            name="x",
            file_url="oss://x",
            file_size=1,
            duration=1.0,
            thumbnail_url=None,
            width=720,
            height=1280,
            fps=24.0,
        )
        resp = _to_generated_video_response(item)
        assert resp.duplicate_rate is None
        assert resp.match_count is None
        assert resp.visual_similarity is None

    def test_storage_failure_falls_back_to_file_url(self):
        storage = MagicMock()
        storage.get_download_url.side_effect = RuntimeError("oss down")
        item = _make_item()
        resp = _to_video_response(item, storage=storage)
        assert resp.download_url == item.file_url
