"""
TTS 配音引擎数据类与纯逻辑测试.

覆盖 VoiceoverSegment / VoiceoverResult / TtsEngine 入口判断等纯逻辑.
TTS 合成调用依赖外部服务，由集成测试覆盖.
"""

from __future__ import annotations

from pathlib import Path
from unittest.mock import MagicMock

import pytest
from video_processing.tts_engine import TtsEngine, VoiceoverResult, VoiceoverSegment

from packages.domain.tts_config import TtsConfig


class TestVoiceoverSegment:
    """配音片段数据类."""

    def test_default_values(self):
        seg = VoiceoverSegment(text="hello")
        assert seg.text == "hello"
        assert seg.start_time == 0.0
        assert seg.end_time == 0.0
        assert seg.audio_path is None
        assert seg.duration == 0.0

    def test_full_values(self):
        seg = VoiceoverSegment(
            text="hello world",
            start_time=1.5,
            end_time=3.0,
            audio_path=Path("/tmp/test.wav"),
            duration=1.5,
        )
        assert seg.text == "hello world"
        assert seg.start_time == 1.5
        assert seg.end_time == 3.0
        assert seg.audio_path == Path("/tmp/test.wav")
        assert seg.duration == 1.5

    def test_duration_calculation(self):
        seg = VoiceoverSegment(text="test", start_time=0.0, end_time=5.5)
        assert seg.end_time - seg.start_time == 5.5


class TestVoiceoverResult:
    """配音结果数据类."""

    def test_default_failure(self):
        result = VoiceoverResult()
        assert result.success is False
        assert result.segments == []
        assert result.total_duration == 0.0
        assert result.error_message == ""

    def test_success_result(self):
        segs = [
            VoiceoverSegment(text="hello", duration=1.0),
            VoiceoverSegment(text="world", duration=2.0),
        ]
        result = VoiceoverResult(
            success=True,
            segments=segs,
            total_duration=3.0,
        )
        assert result.success is True
        assert len(result.segments) == 2
        assert result.total_duration == 3.0
        assert result.error_message == ""

    def test_failure_with_message(self):
        result = VoiceoverResult(success=False, error_message="TTS服务不可用")
        assert result.success is False
        assert result.error_message == "TTS服务不可用"

    def test_segments_isolated_list(self):
        """确保每个实例有独立的segments列表."""
        r1 = VoiceoverResult()
        r2 = VoiceoverResult()
        r1.segments.append(VoiceoverSegment(text="test"))
        assert len(r2.segments) == 0


class TestTtsEngineInit:
    """TTS 引擎初始化."""

    def test_init_creates_work_dir(self, tmp_path):
        mock_tts = MagicMock()
        work_dir = tmp_path / "tts_work"
        engine = TtsEngine(mock_tts, work_dir)
        assert work_dir.exists()
        assert work_dir.is_dir()

    def test_init_with_existing_dir(self, tmp_path):
        mock_tts = MagicMock()
        work_dir = tmp_path / "existing"
        work_dir.mkdir()
        engine = TtsEngine(mock_tts, work_dir)
        assert work_dir.exists()


class TestTtsEngineEntryConditions:
    """TTS 引擎入口判断逻辑（不调用真实 TTS）."""

    def test_disabled_returns_failure(self, tmp_path):
        mock_tts = MagicMock()
        engine = TtsEngine(mock_tts, tmp_path)
        config = TtsConfig(enabled=False, text="hello")
        result = engine.generate_full_voiceover(config)
        assert result.success is False
        assert "未启用" in result.error_message or "空" in result.error_message
        mock_tts.synthesize.assert_not_called()

    def test_empty_text_returns_failure(self, tmp_path):
        mock_tts = MagicMock()
        engine = TtsEngine(mock_tts, tmp_path)
        config = TtsConfig(enabled=True, text="")
        result = engine.generate_full_voiceover(config)
        assert result.success is False
        mock_tts.synthesize.assert_not_called()

    def test_whitespace_text_returns_failure(self, tmp_path):
        mock_tts = MagicMock()
        engine = TtsEngine(mock_tts, tmp_path)
        config = TtsConfig(enabled=True, text="   ")
        result = engine.generate_full_voiceover(config)
        assert result.success is False
        mock_tts.synthesize.assert_not_called()
