# -*- coding: utf-8 -*-
"""测试 Step6 封面生成 400 修复：
1. Worker 渲染完成后提取封面帧写入 cover_url
2. API 创建预览任务时自动关联 source_edit_plan_id
"""

import pytest

from packages.application.generation_tasks import CreateGenerationTaskCommand
from packages.domain.generation_task import GenerationTask, GenerationTaskStatus


def _make_task(**kwargs):
    return GenerationTask(
        id=kwargs.get("id", "task-001"),
        project_id=kwargs.get("project_id", ""),
        asset_library_id=kwargs.get("asset_library_id", ""),
        template_id=kwargs.get("template_id", "tpl-001"),
        created_by_user_id=kwargs.get("user_id", "user-001"),
        asset_ids=kwargs.get("asset_ids", ["asset-1"]),
        status=kwargs.get("status", GenerationTaskStatus.RUNNING),
        source_edit_plan_id=kwargs.get("source_edit_plan_id", ""),
        cover_url=kwargs.get("cover_url", ""),
        is_preview=kwargs.get("is_preview", True),
    )


class TestWorkerCoverFrameExtraction:
    """Worker 端：渲染完成后提取封面帧写入 cover_url"""

    def test_cover_url_set_after_frame_extraction(self):
        """extract_frames 返回结果时，cover_url 应被设置"""
        task = _make_task()
        assert task.cover_url == ""
        mock_frame_url = "https://oss.example.com/frames/frame_001.jpg"
        task.cover_url = mock_frame_url
        assert task.cover_url == mock_frame_url

    def test_cover_url_empty_when_no_frames(self):
        """extract_frames 返回空时，cover_url 应保持为空"""
        task = _make_task()
        assert task.cover_url == ""

    def test_cover_url_preserved_on_extraction_failure(self):
        """extract_frames 异常时，cover_url 保持原值"""
        task = _make_task(cover_url="")
        try:
            raise RuntimeError("MediaKit timeout")
        except RuntimeError:
            pass
        assert task.cover_url == ""

    def test_cover_url_first_frame_used(self):
        """多帧结果应使用第一帧"""
        frames = [
            {"image_url": "https://oss.example.com/frame_001.jpg", "timestamp": 0.0},
            {"image_url": "https://oss.example.com/frame_002.jpg", "timestamp": 1.5},
        ]
        task = _make_task()
        task.cover_url = frames[0]["image_url"]
        assert task.cover_url == "https://oss.example.com/frame_001.jpg"

    def test_cover_url_not_set_when_empty_image_url(self):
        """帧的 image_url 为空时不应设置 cover_url"""
        frames = [{"image_url": "", "timestamp": 0.0}]
        task = _make_task()
        frame_url = frames[0].get("image_url", "")
        if frame_url:
            task.cover_url = frame_url
        assert task.cover_url == ""


class TestPreviewSourceEditPlanId:
    """API 端：预览任务自动关联 source_edit_plan_id"""

    def test_source_edit_plan_id_set_when_provided(self):
        """前端传入 source_edit_plan_id 时应直接使用"""
        cmd = CreateGenerationTaskCommand(
            project_id="",
            asset_library_id="",
            strategy_id="one-take",
            template_id="tpl-001",
            asset_ids=["asset-1"],
            created_by_user_id="user-001",
            source_edit_plan_id="plan-xyz",
        )
        assert cmd.source_edit_plan_id == "plan-xyz"

    def test_source_edit_plan_id_empty_when_not_provided(self):
        """前端未传入时 source_edit_plan_id 默认为空"""
        cmd = CreateGenerationTaskCommand(
            project_id="",
            asset_library_id="",
            strategy_id="one-take",
            template_id="tpl-001",
            asset_ids=["asset-1"],
            created_by_user_id="user-001",
        )
        assert cmd.source_edit_plan_id == ""

    def test_task_preserves_source_edit_plan_id(self):
        """GenerationTask 应保持 source_edit_plan_id"""
        task = _make_task(source_edit_plan_id="plan-abc")
        assert task.source_edit_plan_id == "plan-abc"


class TestCoverRouteStepB:
    """封面路由步骤 B：通过 source_edit_plan_id 查找"""

    def test_step_b_finds_preview_task_by_source_plan(self):
        """步骤 B 应找到 source_edit_plan_id 匹配的已完成预览任务"""
        task = _make_task(
            source_edit_plan_id="plan-abc",
            cover_url="https://oss.example.com/cover.jpg",
            status=GenerationTaskStatus.COMPLETED,
        )
        is_valid = (
            task.source_edit_plan_id == "plan-abc"
            and task.status == GenerationTaskStatus.COMPLETED
            and bool(task.cover_url)
        )
        assert is_valid is True

    def test_step_b_skips_non_completed_tasks(self):
        """步骤 B 应跳过非 completed 状态的任务"""
        task = _make_task(
            source_edit_plan_id="plan-abc",
            cover_url="https://oss.example.com/cover.jpg",
            status=GenerationTaskStatus.FAILED,
        )
        is_valid = task.status == GenerationTaskStatus.COMPLETED and bool(task.cover_url)
        assert is_valid is False

    def test_step_b_skips_tasks_without_cover_url(self):
        """步骤 B 应跳过没有 cover_url 的任务"""
        task = _make_task(
            source_edit_plan_id="plan-abc",
            cover_url="",
            status=GenerationTaskStatus.COMPLETED,
        )
        is_valid = task.status == GenerationTaskStatus.COMPLETED and bool(task.cover_url)
        assert is_valid is False
