"""测试 ASR 字幕路径的标题叠加功能。

验证：
1. _overlay_title_on_ass 函数正确地将标题事件追加到 ASR 生成的 ASS 文件中
2. _maybe_generate_ass 在 ASR 路径中正确叠加标题
3. ASR 无结果但有标题时，仍然生成标题 ASS
4. ASR 失败但有标题时，降级生成标题 ASS
"""

import pytest

pytest.skip("_overlay_title_on_ass 函数已被移除，测试待更新", allow_module_level=True)

from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest

from apps.worker.video_processing.unified_render_service import _overlay_title_on_ass


class TestOverlayTitleOnAss:
    """_overlay_title_on_ass 函数测试"""

    def test_overlay_title_adds_style_and_dialogue(self, tmp_path):
        """标题 Style 和 Dialogue 正确插入 ASS 文件"""
        # 准备一个模拟 ASR 生成的 ASS 文件
        ass_content = """[Script Info]
ScriptType: v4.00+
PlayResX: 1280
PlayResY: 720
ScaledBorderAndShadow: yes
WrapStyle: 2
Encoding: UTF-8

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,思源黑体,24,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1.5,0,2,40,40,60,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:10.00,Default,,0,0,0,,这是ASR字幕
"""
        ass_path = tmp_path / "test.ass"
        ass_path.write_text(ass_content, encoding="utf-8")

        # 叠加标题
        _overlay_title_on_ass(
            ass_path,
            title_text="测试标题",
            title_config={"position": "top", "font": "思源黑体", "size": 48, "color": "#ffffff"},
            video_width=1280,
            video_height=720,
            video_duration=10.0,
        )

        # 验证结果
        result = ass_path.read_text(encoding="utf-8")
        assert "Style: TitleStyle" in result, "TitleStyle 应被插入"
        assert "测试标题" in result, "标题文本应出现在 Dialogue 中"
        # 原有的 ASR 字幕应该保留
        assert "这是ASR字幕" in result, "原有 ASR 字幕应保留"
        # TitleStyle 应该在 Default Style 之后
        lines = result.splitlines()
        style_lines = [i for i, ln in enumerate(lines) if ln.startswith("Style:")]
        assert len(style_lines) >= 2, "应有至少两个 Style 行"

    def test_overlay_title_empty_text_noop(self, tmp_path):
        """空标题文本时不修改 ASS 文件"""
        ass_content = "[Script Info]\n\n[V4+ Styles]\nStyle: Default,test\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:10.00,Default,,0,0,0,,test\n"
        ass_path = tmp_path / "test.ass"
        ass_path.write_text(ass_content, encoding="utf-8")

        _overlay_title_on_ass(
            ass_path,
            title_text="",
            title_config={},
            video_width=1280,
            video_height=720,
            video_duration=10.0,
        )

        result = ass_path.read_text(encoding="utf-8")
        assert "TitleStyle" not in result, "空标题不应添加 TitleStyle"

    def test_overlay_title_preserves_asr_events(self, tmp_path):
        """叠加标题后 ASR 字幕事件保持不变"""
        ass_content = """[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,思源黑体,24,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1.5,0,2,40,40,60,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.50,0:00:03.00,Default,,0,0,0,,第一段字幕
Dialogue: 0,0:00:03.50,0:00:06.00,Default,,0,0,0,,第二段字幕
Dialogue: 0,0:00:06.50,0:00:10.00,Default,,0,0,0,,第三段字幕
"""
        ass_path = tmp_path / "test.ass"
        ass_path.write_text(ass_content, encoding="utf-8")

        _overlay_title_on_ass(
            ass_path,
            title_text="我的标题",
            title_config={"position": "top", "size": 48},
            video_width=1920,
            video_height=1080,
            video_duration=10.0,
        )

        result = ass_path.read_text(encoding="utf-8")
        # 所有 ASR 字幕段都应保留
        assert "第一段字幕" in result
        assert "第二段字幕" in result
        assert "第三段字幕" in result
        # 标题也应存在
        assert "我的标题" in result


class TestMaybeGenerateAssWithTitle:
    """_maybe_generate_ass 方法在 ASR 路径中标题叠加的集成测试"""

    def _make_service(self, tmp_path, plan_config, asr_service=None):
        """创建简化的 UnifiedRenderService 实例用于测试"""
        from apps.worker.video_processing.unified_render_service import UnifiedRenderService

        service = object.__new__(UnifiedRenderService)
        service.plan = MagicMock()
        service.plan.id = "test_plan_001"
        service.plan.config = plan_config
        service.work_dir = tmp_path
        service.output_width = 1280
        service.output_height = 720
        service.asr_service = asr_service
        service._asr_timeline_cached = False
        service._asr_timeline_cache = None
        return service

    def test_asr_path_with_title_overlays_title(self, tmp_path):
        """ASR 路径 + 有标题 → 标题叠加到 ASS 文件"""
        plan_config = {
            "title": {
                "text": "测试标题",
                "enabled": True,
                "position": "top",
                "size": 48,
                "font": "思源黑体",
                "color": "#ffffff",
            },
            "subtitle": {"enabled": True, "auto_generated": True},
        }

        # Mock ASR service
        mock_asr = MagicMock()
        service = self._make_service(tmp_path, plan_config, asr_service=mock_asr)

        # Mock _generate_asr_subtitles to return a timeline with segments
        mock_timeline = MagicMock()
        mock_segment = MagicMock()
        mock_segment.start = 0.0
        mock_segment.end = 3.0
        mock_segment.text = "ASR识别的文字"
        mock_timeline.segments = [mock_segment]
        mock_timeline.segment_count = 1

        with patch.object(service, "_generate_asr_subtitles", return_value=mock_timeline):
            result = service._maybe_generate_ass(video_duration=10.0)

        assert result is not None, "应生成 ASS 文件"
        content = result.read_text(encoding="utf-8")
        assert "测试标题" in content, "标题应出现在 ASS 文件中"
        assert "ASR识别的文字" in content, "ASR 字幕也应保留"

    def test_asr_no_result_with_title_generates_title_ass(self, tmp_path):
        """ASR 无结果 + 有标题 → 仍然生成标题 ASS"""
        plan_config = {
            "title": {"text": "仅标题", "enabled": True, "position": "top", "size": 48},
            "subtitle": {"enabled": True, "auto_generated": True},
        }

        mock_asr = MagicMock()
        service = self._make_service(tmp_path, plan_config, asr_service=mock_asr)

        # Mock ASR returns empty timeline
        mock_timeline = MagicMock()
        mock_timeline.segments = []

        with patch.object(service, "_generate_asr_subtitles", return_value=mock_timeline):
            result = service._maybe_generate_ass(video_duration=10.0)

        assert result is not None, "有标题时应生成 ASS 文件"
        content = result.read_text(encoding="utf-8")
        assert "仅标题" in content, "标题应出现在 ASS 文件中"

    def test_asr_failure_with_title_generates_title_ass(self, tmp_path):
        """ASR 失败 + 有标题 → 降级生成标题 ASS"""
        plan_config = {
            "title": {"text": "降级标题", "enabled": True, "position": "top", "size": 48},
            "subtitle": {"enabled": True, "auto_generated": True},
        }

        mock_asr = MagicMock()
        service = self._make_service(tmp_path, plan_config, asr_service=mock_asr)

        # Mock ASR raises exception
        with patch.object(service, "_generate_asr_subtitles", side_effect=RuntimeError("ASR error")):
            result = service._maybe_generate_ass(video_duration=10.0)

        assert result is not None, "ASR 失败但有标题时应生成 ASS 文件"
        content = result.read_text(encoding="utf-8")
        assert "降级标题" in content, "标题应出现在降级 ASS 文件中"

    def test_overlay_failure_preserves_asr_data(self, tmp_path):
        """_overlay_title_on_ass 抛异常时，ASR 生成的 ASS 文件应保留并返回"""
        plan_config = {
            "title": {"text": "测试标题", "enabled": True, "position": "top", "size": 48},
            "subtitle": {"enabled": True, "auto_generated": True},
        }

        mock_asr = MagicMock()
        service = self._make_service(tmp_path, plan_config, asr_service=mock_asr)

        mock_timeline = MagicMock()
        mock_segment = MagicMock()
        mock_segment.start = 0.0
        mock_segment.end = 3.0
        mock_segment.text = "ASR识别的文字"
        mock_timeline.segments = [mock_segment]
        mock_timeline.segment_count = 1

        with patch.object(service, "_generate_asr_subtitles", return_value=mock_timeline):
            with patch(
                "apps.worker.video_processing.unified_render_service._overlay_title_on_ass",
                side_effect=RuntimeError("模拟叠加标题失败"),
            ):
                result = service._maybe_generate_ass(video_duration=10.0)

        # 即使 _overlay_title_on_ass 失败，仍返回 ASS 文件
        assert result is not None, "应返回 ASS 文件路径"
        assert result.exists(), "ASS 文件应存在"
        content = result.read_text(encoding="utf-8")
        assert "ASR识别的文字" in content, "ASR 字幕数据应保留"
