"""キャラクターのテスト"""

import hashlib
from test.utility import hash_long_string

from fastapi.testclient import TestClient
from pydantic import TypeAdapter
from syrupy.assertion import SnapshotAssertion

from voicevox_engine.metas.Metas import Speaker, SpeakerInfo

_speaker_list_adapter = TypeAdapter(list[Speaker])


def _hash_bytes(value: bytes) -> str:
    """バイト列をハッシュ化する"""
    return "MD5:" + hashlib.md5(value).hexdigest()


def _assert_resource_url(
    client: TestClient, snapshot: SnapshotAssertion, url: str, name: str
) -> None:
    """
    URLからデータが正しく取得できるかスナップショットテストをする
    """
    response = client.get(url)
    assert response.status_code == 200
    assert snapshot(name=name) == _hash_bytes(response.content)


"""
def test_喋れるキャラクター一覧が取得できる(
    client: TestClient, snapshot_json: SnapshotAssertion
) -> None:
    response = client.get("/speakers")
    assert response.status_code == 200
    assert snapshot_json == response.json()


def test_喋れるキャラクターの情報を取得できる(
    client: TestClient, snapshot_json: SnapshotAssertion
) -> None:
    talkers = _speaker_list_adapter.validate_python(client.get("/speakers").json())
    for talker in talkers:
        response = client.get(
            "/speaker_info", params={"speaker_uuid": talker.speaker_uuid}
        )
        assert snapshot_json(
            name=talker.speaker_uuid,
        ) == hash_long_string(response.json())


def test_喋れるキャラクターの情報をURLで取得できる(
    client: TestClient, snapshot_json: SnapshotAssertion, snapshot: SnapshotAssertion
) -> None:
    def assert_resource_url(url: str, name: str) -> None:
        _assert_resource_url(client, snapshot, url, name)

    speakers = _speaker_list_adapter.validate_json(client.get("/speakers").content)
    for speaker in speakers:
        speaker_id = speaker.speaker_uuid
        response = client.get(
            "/speaker_info",
            params={"speaker_uuid": speaker_id, "resource_format": "url"},
        )
        assert snapshot_json(name=speaker_id) == response.json()

        speaker_info = SpeakerInfo.model_validate_json(response.content)
        assert_resource_url(speaker_info.portrait, f"{speaker_id}_portrait")

        for style in speaker_info.style_infos:
            assert_resource_url(style.icon, f"{speaker_id}_{style.id}_icon")
            if style.portrait is not None:
                assert_resource_url(style.portrait, f"{speaker_id}_{style.id}_portrait")
            for i, voice_sample in enumerate(style.voice_samples):
                assert_resource_url(
                    voice_sample, f"{speaker_id}_{style.id}_voice_sample_{i}"
                )
"""


def test_歌えるキャラクター一覧が取得できる(
    client: TestClient, snapshot_json: SnapshotAssertion
) -> None:
    # AivisSpeech Engine では未実装 (501 Not Implemented を返す)
    assert client.get("/singers").status_code == 501
    return
    response = client.get("/singers")
    assert response.status_code == 200
    assert snapshot_json == response.json()


def test_歌えるキャラクターの情報を取得できる(
    client: TestClient, snapshot_json: SnapshotAssertion
) -> None:
    # AivisSpeech Engine では未実装 (501 Not Implemented を返す)
    assert client.get("/singers").status_code == 501
    return
    singers = _speaker_list_adapter.validate_python(client.get("/singers").json())
    for singer in singers:
        response = client.get(
            "/singer_info", params={"speaker_uuid": singer.speaker_uuid}
        )
        assert snapshot_json(
            name=singer.speaker_uuid,
        ) == hash_long_string(response.json())


def test_歌えるキャラクターの情報をURLで取得できる(
    client: TestClient, snapshot_json: SnapshotAssertion, snapshot: SnapshotAssertion
) -> None:
    # AivisSpeech Engine では未実装 (501 Not Implemented を返す)
    assert client.get("/singers").status_code == 501
    return

    def assert_resource_url(url: str, name: str) -> None:
        _assert_resource_url(client, snapshot, url, name)

    singers = _speaker_list_adapter.validate_json(client.get("/singers").content)
    for singer in singers:
        singer_id = singer.speaker_uuid
        response = client.get(
            "/singer_info",
            params={"speaker_uuid": singer_id, "resource_format": "url"},
        )
        assert snapshot_json(name=singer_id) == response.json()

        speaker_info = SpeakerInfo.model_validate_json(response.content)
        assert_resource_url(speaker_info.portrait, f"{singer_id}_portrait")

        for style in speaker_info.style_infos:
            assert_resource_url(style.icon, f"{singer_id}_{style.id}_icon")
            if style.portrait is not None:
                assert_resource_url(style.portrait, f"{singer_id}_{style.id}_portrait")
            for i, voice_sample in enumerate(style.voice_samples):
                assert_resource_url(
                    voice_sample, f"{singer_id}_{style.id}_voice_sample_{i}"
                )
