"""
PresetVoice 预置音色领域模型单元测试
"""

import pytest
from domain.preset_voices import (
    PRESET_VOICES,
    PresetVoice,
    get_preset_voice_by_id,
    get_preset_voices,
    is_preset_voice,
)


class TestPresetVoice:
    """PresetVoice 数据类测试"""

    def test_create_required_fields(self):
        v = PresetVoice(
            voice_id="test_v1",
            name="测试音色",
            description="测试描述",
            gender="female",
        )
        assert v.voice_id == "test_v1"
        assert v.name == "测试音色"
        assert v.description == "测试描述"
        assert v.gender == "female"

    def test_default_language(self):
        v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
        assert v.language == "zh-CN"

    def test_default_preview_url(self):
        v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
        assert v.preview_url == ""

    def test_default_tags_none(self):
        v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
        assert v.tags is None

    def test_custom_tags(self):
        v = PresetVoice(
            voice_id="v1",
            name="n",
            description="d",
            gender="female",
            tags=["温柔", "女声"],
        )
        assert v.tags == ["温柔", "女声"]

    def test_is_frozen(self):
        v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
        with pytest.raises(AttributeError):
            v.name = "改了"


class TestPresetVoiceToDict:
    """to_dict 序列化测试"""

    def test_to_dict_basic(self):
        v = PresetVoice(
            voice_id="longxiaochun_v3",
            name="龙小淳",
            description="温柔女声",
            gender="female",
            language="zh-CN",
            preview_url="https://example.com/audio.mp3",
            tags=["温柔", "女声"],
        )
        d = v.to_dict()
        assert d["voice_id"] == "longxiaochun_v3"
        assert d["name"] == "龙小淳"
        assert d["description"] == "温柔女声"
        assert d["gender"] == "female"
        assert d["language"] == "zh-CN"
        assert d["preview_url"] == "https://example.com/audio.mp3"
        assert d["tags"] == ["温柔", "女声"]

    def test_to_dict_tags_none_becomes_empty_list(self):
        v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
        d = v.to_dict()
        assert d["tags"] == []


class TestPresetVoiceList:
    """预置音色列表测试"""

    def test_list_not_empty(self):
        voices = get_preset_voices()
        assert len(voices) > 0

    def test_all_are_preset_voice_instances(self):
        for v in PRESET_VOICES:
            assert isinstance(v, PresetVoice)

    def test_voice_ids_unique(self):
        ids = [v.voice_id for v in PRESET_VOICES]
        assert len(ids) == len(set(ids))

    def test_all_have_required_fields(self):
        for v in PRESET_VOICES:
            assert v.voice_id
            assert v.name
            assert v.description
            assert v.gender in ("male", "female")
            assert v.language

    def test_total_count(self):
        assert len(PRESET_VOICES) == 8


class TestGetPresetVoiceById:
    """按 ID 查询预置音色测试"""

    def test_existing_voice(self):
        v = get_preset_voice_by_id("longxiaochun_v3")
        assert v is not None
        assert v.name == "龙小淳"
        assert v.gender == "female"

    def test_nonexistent_voice(self):
        v = get_preset_voice_by_id("nonexistent_voice")
        assert v is None

    def test_empty_string(self):
        v = get_preset_voice_by_id("")
        assert v is None


class TestIsPresetVoice:
    """判断是否预置音色测试"""

    def test_existing_is_preset(self):
        assert is_preset_voice("longsanshu_v3") is True

    def test_nonexistent_not_preset(self):
        assert is_preset_voice("custom_voice_123") is False

    def test_empty_not_preset(self):
        assert is_preset_voice("") is False


class TestPresetVoiceSamples:
    """预置音色样本验证"""

    @pytest.mark.parametrize(
        "voice_id,expected_name,gender",
        [
            ("longxiaochun_v3", "龙小淳", "female"),
            ("longxiaoxia_v3", "龙小夏", "female"),
            ("longsanshu_v3", "龙三叔", "male"),
            ("longyue_v3", "龙悦", "female"),
            ("longshu_v3", "龙书", "male"),
            ("longyingjing_v3", "龙应静", "female"),
            ("longshuo_v3", "龙硕", "male"),
            ("longtian_v3", "龙甜", "female"),
        ],
    )
    def test_all_preset_voices_sample(self, voice_id, expected_name, gender):
        v = get_preset_voice_by_id(voice_id)
        assert v is not None
        assert v.name == expected_name
        assert v.gender == gender
        assert v.language == "zh-CN"
        assert len(v.tags or []) >= 2
