"""转场引擎单元测试 - 配置解析等纯逻辑."""

from __future__ import annotations

import pytest
from video_processing.transition_engine import (
    CUT_TRANSITION,
    DEFAULT_TRANSITION_DURATION,
    MAX_TRANSITION_DURATION,
    MIN_TRANSITION_DURATION,
    TransitionConfig,
    TransitionType,
)


class TestTransitionConstants:
    """常量测试."""

    def test_duration_ranges(self):
        """时长范围合理."""
        assert MIN_TRANSITION_DURATION == 0.3
        assert MAX_TRANSITION_DURATION == 2.0
        assert DEFAULT_TRANSITION_DURATION == 0.5
        assert MIN_TRANSITION_DURATION < DEFAULT_TRANSITION_DURATION < MAX_TRANSITION_DURATION

    def test_cut_transition_value(self):
        """cut转场值."""
        assert CUT_TRANSITION == "cut"


class TestTransitionType:
    """TransitionType 枚举测试."""

    def test_supports_fade(self):
        """支持fade."""
        assert TransitionType.is_supported("fade") is True

    def test_supports_cut(self):
        """cut也在TransitionType枚举中."""
        assert "cut" in [t.value for t in TransitionType]

    def test_unsupported_effect(self):
        """不支持的效果."""
        assert TransitionType.is_supported("nonexistent_effect_xyz") is False

    def test_is_supported_case_insensitive(self):
        """是否大小写不敏感（看实现）."""
        # 直接测试几个已知的
        assert TransitionType.is_supported("fade") is True
        assert TransitionType.is_supported("dissolve") is True

    def test_all_types_have_value(self):
        """所有枚举都有有效值."""
        for t in TransitionType:
            assert isinstance(t.value, str)
            assert len(t.value) > 0


class TestTransitionConfigParse:
    """TransitionConfig.parse 解析测试."""

    def test_no_args_default(self):
        """无参数默认配置."""
        config = TransitionConfig.parse()
        assert config.effect == CUT_TRANSITION
        assert config.duration == DEFAULT_TRANSITION_DURATION

    def test_none_effect_default(self):
        """None effect默认为cut."""
        config = TransitionConfig.parse(effect=None)
        assert config.effect == CUT_TRANSITION

    def test_empty_effect_default(self):
        """空字符串effect默认为cut."""
        config = TransitionConfig.parse(effect="")
        assert config.effect == CUT_TRANSITION

    def test_whitespace_effect_default(self):
        """空白effect默认为cut."""
        config = TransitionConfig.parse(effect="   ")
        assert config.effect == CUT_TRANSITION

    def test_fade_effect(self):
        """fade效果."""
        config = TransitionConfig.parse(effect="fade")
        assert config.effect == "fade"

    def test_unsupported_effect_falls_back_to_cut(self):
        """不支持的效果降级到cut."""
        config = TransitionConfig.parse(effect="super_cool_effect")
        assert config.effect == CUT_TRANSITION

    def test_cut_effect(self):
        """显式cut效果."""
        config = TransitionConfig.parse(effect="cut")
        assert config.effect == CUT_TRANSITION

    def test_custom_duration(self):
        """自定义时长."""
        config = TransitionConfig.parse(duration=1.0)
        assert config.duration == 1.0

    def test_duration_below_min_clamped(self):
        """时长低于最小值钳制."""
        config = TransitionConfig.parse(duration=0.1)
        assert config.duration == MIN_TRANSITION_DURATION

    def test_duration_above_max_clamped(self):
        """时长高于最大值钳制."""
        config = TransitionConfig.parse(duration=5.0)
        assert config.duration == MAX_TRANSITION_DURATION

    def test_duration_at_min(self):
        """时长边界最小值."""
        config = TransitionConfig.parse(duration=MIN_TRANSITION_DURATION)
        assert config.duration == MIN_TRANSITION_DURATION

    def test_duration_at_max(self):
        """时长边界最大值."""
        config = TransitionConfig.parse(duration=MAX_TRANSITION_DURATION)
        assert config.duration == MAX_TRANSITION_DURATION

    def test_invalid_duration_falls_back(self):
        """无效时长回退到默认."""
        config = TransitionConfig.parse(duration="not_a_number")
        assert config.duration == DEFAULT_TRANSITION_DURATION

    def test_none_duration_default(self):
        """None时长用默认值."""
        config = TransitionConfig.parse(duration=None)
        assert config.duration == DEFAULT_TRANSITION_DURATION

    def test_effect_and_duration(self):
        """同时指定效果和时长."""
        config = TransitionConfig.parse(effect="fade", duration=1.0)
        assert config.effect == "fade"
        assert config.duration == 1.0


class TestIsCut:
    """is_cut 属性测试."""

    def test_cut_is_cut(self):
        """cut是硬切."""
        config = TransitionConfig(effect=CUT_TRANSITION, duration=0.5)
        assert config.is_cut is True

    def test_fade_not_cut(self):
        """fade不是硬切."""
        config = TransitionConfig(effect="fade", duration=0.5)
        assert config.is_cut is False


class TestFfmpegTransition:
    """ffmpeg_transition 属性测试."""

    def test_cut_returns_empty(self):
        """cut返回空字符串."""
        config = TransitionConfig(effect=CUT_TRANSITION, duration=0.5)
        assert config.ffmpeg_transition == ""

    def test_fade_returns_fade(self):
        """fade返回fade."""
        config = TransitionConfig(effect="fade", duration=0.5)
        result = config.ffmpeg_transition
        assert isinstance(result, str)
        assert len(result) > 0

    def test_valid_effect_has_ffmpeg_name(self):
        """所有非cut的支持效果都有对应的ffmpeg名称."""
        for t in TransitionType:
            if t.value == CUT_TRANSITION:
                continue  # cut返回空是正常的
            config = TransitionConfig(effect=t.value, duration=0.5)
            assert config.ffmpeg_transition != ""
