"""#1749 generation_preview 配音分配分支测试。

直接测试 create_preview_generation_task 中配音分配逻辑:
- count=1: apply_voice_duration_to_plan 被调用
- count>1: ensure_variant_plans / clone + reselect 路径
"""

from __future__ import annotations

from unittest.mock import MagicMock, call, patch

import pytest

# ── 辅助 ──────────────────────────────────────────────────────────────────────


def _make_user():
    mu = MagicMock()
    mu.user.id = "u1"
    return mu


def _make_task(source_plan_id="src_plan_1"):
    t = MagicMock()
    t.id = "task_1"
    t.source_edit_plan_id = source_plan_id
    t.extra_meta = {}
    return t


# ═══════════════════════════════════════════════════════════════════════════════
# 直接测 apply_voice_duration_to_plan 的调用入口
# ═══════════════════════════════════════════════════════════════════════════════


class TestPreviewCount1VoiceAllocation:
    """count=1 预览: clone_plan_for_variant + apply_voice_duration_to_plan。"""

    def test_clone_then_apply_voice(self):
        """验证 count=1 且有配音时, clone + apply 被调用。"""
        from app.services.edit_plan_service import EditPlanService

        db = MagicMock()
        svc = EditPlanService.__new__(EditPlanService)
        svc._clip_repo = MagicMock()
        svc._clip_repo.session = db
        svc._plan_repo = MagicMock()
        svc._generation_task_repo = MagicMock()

        variant_plan = MagicMock()
        variant_plan.id = "v_plan_0"
        svc.clone_plan_for_variant = MagicMock(return_value=variant_plan)
        svc.apply_voice_duration_to_plan = MagicMock(return_value=variant_plan)

        # 模拟 count=1 预览配音分配逻辑
        source_plan_id = "src_plan_1"
        voice_durations = [30.0]

        if source_plan_id:
            vp = svc.clone_plan_for_variant(
                source_plan_id,
                created_by_user_id="u1",
                name_suffix="预览变体",
            )
            if voice_durations and voice_durations[0] > 0:
                svc.apply_voice_duration_to_plan(vp.id, voice_durations[0])

        svc.clone_plan_for_variant.assert_called_once_with(
            source_plan_id,
            created_by_user_id="u1",
            name_suffix="预览变体",
        )
        svc.apply_voice_duration_to_plan.assert_called_once_with("v_plan_0", 30.0)

    def test_clone_without_voice_when_duration_zero(self):
        """voice_durations[0]=0 时不调用 apply。"""
        from app.services.edit_plan_service import EditPlanService

        svc = EditPlanService.__new__(EditPlanService)
        svc._clip_repo = MagicMock()
        svc._plan_repo = MagicMock()
        svc._generation_task_repo = MagicMock()

        vp = MagicMock(id="v_plan_0")
        svc.clone_plan_for_variant = MagicMock(return_value=vp)
        svc.apply_voice_duration_to_plan = MagicMock()

        voice_durations = [0.0]
        variant_plan = svc.clone_plan_for_variant("src", created_by_user_id="u1", name_suffix="预览变体")
        if voice_durations and voice_durations[0] > 0:
            svc.apply_voice_duration_to_plan(variant_plan.id, voice_durations[0])

        svc.apply_voice_duration_to_plan.assert_not_called()


class TestPreviewCountGt1VoiceAllocation:
    """count>1 预览: ensure_variant_plans 路径。"""

    def test_ensure_variant_plans_called(self):
        """验证 count>1 时 ensure_variant_plans 被正确调用。"""
        from app.services.edit_plan_service import EditPlanService

        svc = EditPlanService.__new__(EditPlanService)
        svc._clip_repo = MagicMock()
        svc._plan_repo = MagicMock()
        svc._generation_task_repo = MagicMock()

        svc.ensure_variant_plans = MagicMock(return_value=["p0", "p1", "p2"])

        result = svc.ensure_variant_plans(
            "src_plan",
            3,
            ["a1", "a2"],
            created_by_user_id="u1",
            voice_durations=[30.0, 20.0, 15.0],
        )

        assert result == ["p0", "p1", "p2"]
        svc.ensure_variant_plans.assert_called_once_with(
            "src_plan",
            3,
            ["a1", "a2"],
            created_by_user_id="u1",
            voice_durations=[30.0, 20.0, 15.0],
        )

    def test_ensure_variant_plans_no_voice(self):
        """无配音时 voice_durations 全 0 仍可调用。"""
        from app.services.edit_plan_service import EditPlanService

        svc = EditPlanService.__new__(EditPlanService)
        svc._clip_repo = MagicMock()
        svc._plan_repo = MagicMock()
        svc._generation_task_repo = MagicMock()

        svc.ensure_variant_plans = MagicMock(return_value=["p0"])

        result = svc.ensure_variant_plans(
            "src_plan",
            1,
            ["a1"],
            created_by_user_id="u1",
            voice_durations=None,
        )
        assert result == ["p0"]
