"""片头片尾引擎单元测试 - 配置解析等纯逻辑."""

from __future__ import annotations

import pytest
from video_processing.intro_outro_engine import IntroOutroConfig


class TestIntroOutroConfigDefaults:
    """默认配置测试."""

    def test_default_values(self):
        """默认值正确."""
        config = IntroOutroConfig()
        assert config.enabled is False
        assert config.intro_type == "none"
        assert config.outro_type == "none"
        assert config.intro_duration == 3.0
        assert config.outro_duration == 3.0
        assert config.transition_effect == "fade"
        assert config.transition_duration == 0.5


class TestIntroOutroConfigFromDict:
    """from_dict 配置解析测试."""

    def test_none_returns_default(self):
        """None 返回默认配置."""
        config = IntroOutroConfig.from_dict(None)
        assert config.enabled is False

    def test_empty_dict_returns_default(self):
        """空 dict 返回默认."""
        config = IntroOutroConfig.from_dict({})
        assert config.enabled is False

    def test_disabled_returns_default(self):
        """enabled=False 返回默认."""
        config = IntroOutroConfig.from_dict({"enabled": False})
        assert config.enabled is False

    def test_enabled_defaults(self):
        """启用时默认值正确."""
        config = IntroOutroConfig.from_dict({"enabled": True})
        assert config.enabled is True
        assert config.intro_type == "none"
        assert config.outro_type == "none"

    def test_text_intro(self):
        """文字片头配置."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "intro": {
                "type": "text",
                "title": "我的片头",
                "subtitle": "欢迎收看",
            },
        })
        assert config.intro_type == "text"
        assert config.intro_title == "我的片头"
        assert config.intro_subtitle == "欢迎收看"

    def test_video_intro(self):
        """视频片头配置."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "intro": {
                "type": "video",
                "video_path": "/videos/intro.mp4",
                "duration": 5.0,
            },
        })
        assert config.intro_type == "video"
        assert config.intro_video_path == "/videos/intro.mp4"
        assert config.intro_duration == 5.0

    def test_video_intro_video_alias(self):
        """video 字段作为 video_path 别名."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "intro": {
                "type": "video",
                "video": "/videos/intro.mp4",
            },
        })
        assert config.intro_video_path == "/videos/intro.mp4"

    def test_text_outro(self):
        """文字片尾配置."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "outro": {
                "type": "text",
                "title": "感谢观看",
                "subtitle": "点赞关注",
            },
        })
        assert config.outro_type == "text"
        assert config.outro_title == "感谢观看"
        assert config.outro_subtitle == "点赞关注"

    def test_outro_default_title(self):
        """片尾默认标题."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "outro": {"type": "text"},
        })
        assert config.outro_title == "感谢观看"
        assert config.outro_subtitle == "点赞关注不迷路"

    def test_text_intro_styling(self):
        """文字片头样式配置."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "intro": {
                "type": "text",
                "title": "测试",
                "background": "#FF0000",
                "title_color": "yellow",
                "title_size": 64,
                "subtitle_color": "white",
                "subtitle_size": 32,
            },
        })
        assert config.intro_background == "#FF0000"
        assert config.intro_title_color == "yellow"
        assert config.intro_title_size == 64
        assert config.intro_subtitle_color == "white"
        assert config.intro_subtitle_size == 32

    def test_transition_config(self):
        """转场配置."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "transition": "dissolve",
            "transition_duration": 1.0,
        })
        assert config.transition_effect == "dissolve"
        assert config.transition_duration == 1.0

    def test_empty_intro_dict(self):
        """空 intro dict."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "intro": {},
        })
        assert config.intro_type == "none"

    def test_none_intro(self):
        """None intro 值."""
        config = IntroOutroConfig.from_dict({
            "enabled": True,
            "intro": None,
        })
        assert config.intro_type == "none"


class TestHasIntroOutro:
    """has_intro / has_outro 属性测试."""

    def test_no_intro_when_disabled(self):
        """禁用时无片头."""
        config = IntroOutroConfig()
        assert config.has_intro is False
        assert config.has_outro is False

    def test_video_intro_has_intro(self):
        """视频片头有has_intro."""
        config = IntroOutroConfig(
            enabled=True,
            intro_type="video",
            intro_video_path="/a.mp4",
        )
        assert config.has_intro is True

    def test_text_intro_has_intro(self):
        """文字片头有has_intro."""
        config = IntroOutroConfig(
            enabled=True,
            intro_type="text",
            intro_title="test",
        )
        assert config.has_intro is True

    def test_none_intro_no_intro(self):
        """none类型无片头."""
        config = IntroOutroConfig(enabled=True, intro_type="none")
        assert config.has_intro is False

    def test_video_outro_has_outro(self):
        """视频片尾有has_outro."""
        config = IntroOutroConfig(
            enabled=True,
            outro_type="video",
            outro_video_path="/a.mp4",
        )
        assert config.has_outro is True

    def test_text_outro_has_outro(self):
        """文字片尾有has_outro."""
        config = IntroOutroConfig(
            enabled=True,
            outro_type="text",
            outro_title="test",
        )
        assert config.has_outro is True

    def test_follow_outro_has_outro(self):
        """follow类型片尾有has_outro."""
        config = IntroOutroConfig(
            enabled=True,
            outro_type="follow",
            outro_title="test",
        )
        assert config.has_outro is True


class TestValidate:
    """validate 配置校验测试."""

    def test_disabled_valid(self):
        """禁用配置合法."""
        config = IntroOutroConfig()
        ok, msg = config.validate()
        assert ok is True
        assert msg == ""

    def test_video_intro_missing_path(self):
        """视频片头缺少路径."""
        config = IntroOutroConfig(
            enabled=True,
            intro_type="video",
            intro_video_path="",
        )
        ok, msg = config.validate()
        assert ok is False
        assert "video_path" in msg

    def test_text_intro_missing_title(self):
        """文字片头缺少标题."""
        config = IntroOutroConfig(
            enabled=True,
            intro_type="text",
            intro_title="",
        )
        ok, msg = config.validate()
        assert ok is False
        assert "title" in msg

    def test_video_outro_missing_path(self):
        """视频片尾缺少路径."""
        config = IntroOutroConfig(
            enabled=True,
            outro_type="video",
            outro_video_path="",
        )
        ok, msg = config.validate()
        assert ok is False
        assert "video_path" in msg

    def test_text_outro_missing_title(self):
        """文字片尾缺少标题."""
        config = IntroOutroConfig(
            enabled=True,
            outro_type="text",
            outro_title="",
        )
        ok, msg = config.validate()
        assert ok is False
        assert "title" in msg

    def test_zero_intro_duration_invalid(self):
        """片头时长为0无效."""
        config = IntroOutroConfig(
            enabled=True,
            intro_type="text",
            intro_title="test",
            intro_duration=0,
        )
        ok, msg = config.validate()
        assert ok is False
        assert "时长" in msg

    def test_negative_outro_duration_invalid(self):
        """片尾时长为负无效."""
        config = IntroOutroConfig(
            enabled=True,
            outro_type="text",
            outro_title="test",
            outro_duration=-1.0,
        )
        ok, msg = config.validate()
        assert ok is False
        assert "时长" in msg

    def test_valid_text_both(self):
        """文字片头片尾都合法."""
        config = IntroOutroConfig(
            enabled=True,
            intro_type="text",
            intro_title="片头",
            intro_duration=3.0,
            outro_type="text",
            outro_title="片尾",
            outro_duration=3.0,
        )
        ok, msg = config.validate()
        assert ok is True
