"""Tests fuer die TTS-Text-Normalisierung (Aussprache vor Piper)."""

import asyncio

from app.pipeline.tts_normalizer import TTSNormalizer
from app.pipeline.spoken_response_adapter import SpokenResponseAdapter
from app.pipeline import german_numbers as gn


def _run(coro):
    return asyncio.run(coro)


def _norm(text, level="full", language="de"):
    return _run(TTSNormalizer().run(text, language=language, level=level))


# --- Ordinalzahlen ---------------------------------------------------------

def test_date_ordinal_to_attributive():
    assert "erster Mai" in _norm("Am 1. Mai feiern wir.")
    assert "dritter Oktober" in _norm("Der 3. Oktober ist ein Feiertag.")


def test_enumeration_run_to_adverbial():
    out = _norm("1. 2. 3. fertig")
    assert "erstens" in out and "zweitens" in out and "drittens" in out


def test_enum_marker_paren():
    assert "erstens" in _norm("1) Milch")
    assert "zweitens" in _norm("2.) Eier")


def test_plain_trailing_number_not_touched():
    # Eine einzelne Zahl am Satzende ist KEINE Ordinalzahl -> bleibt Zahl.
    out = _norm("Ich nehme 5.")
    assert "fünftens" not in out and "fünfter" not in out
    assert "5" in out


# --- Einheiten -------------------------------------------------------------

def test_units_after_number():
    assert "Kilogramm" in _norm("Das wiegt 10 kg.")
    assert "Kilometer pro Stunde" in _norm("Tempo 50 km/h.")


def test_unit_letter_not_triggered_without_number():
    # "m" ohne vorangehende Zahl darf nicht zu "Meter" werden.
    assert "Meter" not in _norm("Am Morgen.")


# --- Abkuerzungen / Lexikon ------------------------------------------------

def test_builtin_abbreviations():
    assert "Doktor" in _norm("Dr. Müller kommt.")
    assert "und so weiter" in _norm("Brot, Milch usw.")


# --- Stufen ----------------------------------------------------------------

def test_light_leaves_numbers_and_abbrev_for_cloud():
    out = _norm("Am 1. Mai wiegt es 10 kg, Dr. Müller.", level="light")
    assert "erster" not in out and "Kilogramm" not in out and "Doktor" not in out
    assert "1." in out and "kg" in out  # Cloud-TTS macht das selbst

def test_off_returns_unchanged():
    src = "Am 1. Mai, 10 kg."
    assert _norm(src, level="off") == src


def test_url_and_email_squashed_in_light():
    out = _norm("Schau auf https://example.org oder mail@example.org.", level="light")
    assert "Link" in out and "E-Mail-Adresse" in out


# --- Zusammenspiel mit dem SpokenResponseAdapter ---------------------------

def test_adapter_numbered_list_to_ordinal():
    md = "1. Milch\n2. Eier\n3. Brot"
    out = _run(SpokenResponseAdapter().run(md))
    assert "erstens, Milch" in out and "zweitens, Eier" in out


def test_terms_dict_is_case_insensitive():
    from app.pipeline.tts_normalizer import _apply_dict
    mapping = {"strömt": "ströhmt"}
    assert _apply_dict("Der Bach strömt.", mapping, ignore_case=True) == "Der Bach ströhmt."
    # Satzanfang (Großschreibung) wird ebenfalls erfasst.
    assert _apply_dict("Strömt es?", mapping, ignore_case=True) == "ströhmt es?"
    # Teilwort wird NICHT getroffen (Wortgrenze).
    assert _apply_dict("Strömung", mapping, ignore_case=True) == "Strömung"


def test_german_numbers_table():
    assert gn.ordinal_attributive(1) == "erster"
    assert gn.ordinal_adverbial(3) == "drittens"
    assert gn.has_ordinal(31) and not gn.has_ordinal(32)
