"""Тесты для морфологического движка — повышение покрытия с 55% до ~85%+."""
from __future__ import annotations

from texthumanize.morphology import MorphologyEngine, get_morphology

# ═══════════════════════════════════════════════════════════════
#  Русский язык
# ═══════════════════════════════════════════════════════════════

class TestRussianLemmatization:
    """Тесты лемматизации русских слов."""

    def setup_method(self):
        self.m = MorphologyEngine("ru")

    def test_adjective_endpoints(self):
        """Прилагательные: различные окончания → базовая форма."""
        # -ого → -ый/ий
        result = self.m.lemmatize("красивого")
        assert result.endswith(("ый", "ий", "ой"))

    def test_verb_endings(self):
        """Глаголы: спряжённые формы → инфинитив."""
        result = self.m.lemmatize("делает")
        assert result.endswith("ть")

    def test_short_word(self):
        """Слова короче 3 символов возвращаются как есть."""
        assert self.m.lemmatize("на") == "на"
        assert self.m.lemmatize("в") == "в"

    def test_generate_forms_adj(self):
        """Генерация форм прилагательного."""
        forms = self.m.generate_forms("красивый")
        assert "красивый" in forms
        assert len(forms) > 3

    def test_generate_forms_verb_i(self):
        """Генерация форм глагола I спряжения (-ать)."""
        forms = self.m.generate_forms("делать")
        assert "делать" in forms
        assert len(forms) > 3

    def test_generate_forms_verb_ii(self):
        """Генерация форм глагола II спряжения (-ить)."""
        forms = self.m.generate_forms("говорить")
        assert "говорить" in forms
        assert len(forms) > 3

    def test_generate_forms_noun_a(self):
        """Генерация форм существительного на -а."""
        forms = self.m.generate_forms("школа")
        assert "школа" in forms
        assert any("ы" in f for f in forms)

    def test_generate_forms_noun_o(self):
        """Генерация форм существительного на -о."""
        forms = self.m.generate_forms("окно")
        assert "окно" in forms
        assert len(forms) > 3

    def test_generate_forms_noun_ya(self):
        """Генерация форм существительного на -я."""
        forms = self.m.generate_forms("земля")
        assert "земля" in forms
        assert len(forms) > 3

    def test_generate_forms_noun_consonant(self):
        """Генерация форм существительного м.р. (нулевое окончание)."""
        forms = self.m.generate_forms("стол")
        assert "стол" in forms
        assert any("а" in f for f in forms)

    def test_detect_pos_adj(self):
        """Определение прилагательного."""
        assert self.m.detect_pos("красивый") == "adj"

    def test_detect_pos_verb(self):
        """Определение глагола."""
        assert self.m.detect_pos("делать") == "verb"

    def test_detect_pos_noun(self):
        """Существительное (по умолчанию для slave языков)."""
        assert self.m.detect_pos("стол") == "noun"

    def test_detect_pos_adv(self):
        """Наречие с суффиксом -ски, -чески."""
        assert self.m.detect_pos("практически") == "adv"

    def test_match_form_slavic_adj(self):
        """Подбор формы прилагательного-синонима."""
        result = self.m.find_synonym_form("красивого", "большой")
        # Должен попытаться подставить окончание
        assert isinstance(result, str)
        assert len(result) > 0

    def test_match_form_slavic_verb(self):
        """Подбор формы глагола-синонима."""
        result = self.m.find_synonym_form("делает", "работать")
        assert isinstance(result, str)

    def test_is_same_lemma_true(self):
        """Два слова с одной леммой."""
        # Одно и то же слово
        assert self.m.is_same_lemma("делает", "делает")

    def test_is_same_lemma_false(self):
        """Два разных слова."""
        assert not self.m.is_same_lemma("делать", "играть")


# ═══════════════════════════════════════════════════════════════
#  Украинский язык
# ═══════════════════════════════════════════════════════════════

class TestUkrainianMorphology:
    """Тесты украинской морфологии."""

    def setup_method(self):
        self.m = MorphologyEngine("uk")

    def test_lemmatize_adj(self):
        """Лемматизация украинского прилагательного."""
        result = self.m.lemmatize("красивого")
        assert isinstance(result, str)

    def test_lemmatize_verb(self):
        """Лемматизация украинского глагола."""
        result = self.m.lemmatize("робить")
        assert isinstance(result, str)

    def test_generate_forms(self):
        """Генерация форм украинского прилагательного."""
        forms = self.m.generate_forms("гарний")
        assert "гарний" in forms
        assert len(forms) >= 1

    def test_detect_pos(self):
        """Определение части речи для украинского."""
        assert self.m.detect_pos("робити") == "verb"


# ═══════════════════════════════════════════════════════════════
#  Английский язык
# ═══════════════════════════════════════════════════════════════

class TestEnglishMorphology:
    """Тесты английской морфологии."""

    def setup_method(self):
        self.m = MorphologyEngine("en")

    def test_lemmatize_irregular(self):
        """Неправильные глаголы: went → go."""
        result = self.m.lemmatize("went")
        assert result == "go"

    def test_lemmatize_ing_double_consonant(self):
        """running → run (удаление двойной согласной + -ing)."""
        result = self.m.lemmatize("running")
        assert result == "run"

    def test_lemmatize_ing_vowel_stem(self):
        """playing → play."""
        result = self.m.lemmatize("playing")
        assert result == "play"

    def test_lemmatize_ing_consonant_stem(self):
        """making → make (+ silent e)."""
        result = self.m.lemmatize("making")
        assert result == "make"

    def test_lemmatize_ied(self):
        """carried → carry."""
        assert self.m.lemmatize("carried") == "carry"

    def test_lemmatize_ies(self):
        """carries → carry."""
        assert self.m.lemmatize("carries") == "carry"

    def test_lemmatize_ed_double_consonant(self):
        """stopped → stop."""
        assert self.m.lemmatize("stopped") == "stop"

    def test_lemmatize_ed_vowel_stem(self):
        """played → play."""
        assert self.m.lemmatize("played") == "play"

    def test_lemmatize_ed_consonant(self):
        """hoped → hope."""
        assert self.m.lemmatize("hoped") == "hope"

    def test_lemmatize_es_shes(self):
        """dishes → dish."""
        assert self.m.lemmatize("dishes") == "dish"

    def test_lemmatize_es_ses(self):
        """houses → house."""
        assert self.m.lemmatize("houses") == "house"

    def test_lemmatize_es_generic(self):
        """goes → go (generic -es removal)."""
        result = self.m.lemmatize("goes")
        assert isinstance(result, str)

    def test_lemmatize_s(self):
        """plays → play."""
        assert self.m.lemmatize("plays") == "play"

    def test_lemmatize_er(self):
        """bigger → bigg (rough estimate)."""
        result = self.m.lemmatize("bigger")
        assert isinstance(result, str)

    def test_lemmatize_est(self):
        """biggest → bigg (rough estimate)."""
        result = self.m.lemmatize("biggest")
        assert isinstance(result, str)

    def test_lemmatize_ly(self):
        """quickly → quick."""
        assert self.m.lemmatize("quickly") == "quick"

    def test_lemmatize_ly_y(self):
        """happily → happy."""
        assert self.m.lemmatize("happily") == "happy"

    def test_lemmatize_short(self):
        """Короткие слова возвращаются как есть."""
        assert self.m.lemmatize("go") == "go"

    def test_generate_forms_irregular(self):
        """Генерация форм неправильного глагола."""
        forms = self.m.generate_forms("go")
        assert "go" in forms
        assert len(forms) > 2

    def test_generate_forms_regular_e(self):
        """Генерация форм глагола на -e."""
        forms = self.m.generate_forms("make")
        assert "make" in forms
        assert "makes" in forms
        assert "making" in forms

    def test_generate_forms_regular_y(self):
        """Генерация форм слова на -y (consonant+y)."""
        forms = self.m.generate_forms("carry")
        assert "carry" in forms
        assert "carries" in forms

    def test_generate_forms_regular(self):
        """Генерация форм обычного слова."""
        forms = self.m.generate_forms("play")
        assert "play" in forms
        assert "plays" in forms
        assert "playing" in forms

    def test_match_form_ing(self):
        """Подбор формы -ing."""
        result = self.m.find_synonym_form("running", "play")
        assert result == "playing"

    def test_match_form_ed(self):
        """Подбор формы -ed."""
        result = self.m.find_synonym_form("played", "work")
        assert result == "worked"

    def test_match_form_s(self):
        """Подбор формы -s."""
        result = self.m.find_synonym_form("plays", "work")
        assert result == "works"

    def test_match_form_es(self):
        """Подбор формы -es."""
        result = self.m.find_synonym_form("goes", "work")
        assert result == "works"

    def test_match_form_ies(self):
        """Подбор формы -ies."""
        result = self.m.find_synonym_form("carries", "hurry")
        assert result == "hurries"

    def test_match_form_ly(self):
        """Подбор формы -ly."""
        result = self.m.find_synonym_form("quickly", "slow")
        assert result == "slowly"

    def test_match_form_ly_y(self):
        """Подбор формы -ly для слова на -y."""
        result = self.m.find_synonym_form("happily", "easy")
        assert result == "easily"

    def test_match_form_er(self):
        """Подбор формы -er."""
        result = self.m.find_synonym_form("bigger", "small")
        assert result == "smaller"

    def test_match_form_est(self):
        """Подбор формы -est."""
        result = self.m.find_synonym_form("biggest", "small")
        assert result == "smallest"

    def test_detect_pos_adv(self):
        """Наречие на -ly."""
        assert self.m.detect_pos("quickly") == "adv"

    def test_detect_pos_verb(self):
        """Глагол на -ing."""
        assert self.m.detect_pos("running") == "verb"

    def test_detect_pos_noun(self):
        """Существительное на -tion."""
        assert self.m.detect_pos("information") == "noun"

    def test_detect_pos_adj(self):
        """Прилагательное на -ful."""
        assert self.m.detect_pos("beautiful") == "adj"

    def test_detect_pos_other(self):
        """Неопределяемая часть речи."""
        assert self.m.detect_pos("the") == "other"


# ═══════════════════════════════════════════════════════════════
#  Немецкий язык
# ═══════════════════════════════════════════════════════════════

class TestGermanMorphology:
    """Тесты немецкой морфологии."""

    def setup_method(self):
        self.m = MorphologyEngine("de")

    def test_lemmatize_adj(self):
        """Лемматизация прилагательного."""
        result = self.m.lemmatize("schöner")
        assert isinstance(result, str)

    def test_lemmatize_verb(self):
        """Лемматизация глагола."""
        result = self.m.lemmatize("macht")
        assert result.endswith("en")

    def test_lemmatize_short(self):
        """Короткое слово."""
        assert self.m.lemmatize("ab") == "ab"

    def test_generate_forms_adj(self):
        """Генерация форм прилагательного."""
        forms = self.m.generate_forms("schön")
        assert "schön" in forms
        assert "schöne" in forms

    def test_generate_forms_verb(self):
        """Генерация форм глагола на -en."""
        forms = self.m.generate_forms("machen")
        assert "machen" in forms
        assert "macht" in forms

    def test_generate_forms_noun(self):
        """Генерация форм существительного."""
        forms = self.m.generate_forms("Haus")
        assert "Haus" in forms
        assert len(forms) > 3

    def test_match_form_adj(self):
        """Подбор формы прилагательного-синонима."""
        result = self.m.find_synonym_form("großer", "klein")
        assert isinstance(result, str)
        assert len(result) > 0

    def test_match_form_verb(self):
        """Подбор формы глагола-синонима."""
        result = self.m.find_synonym_form("macht", "spielen")
        assert isinstance(result, str)

    def test_detect_pos_noun(self):
        """Существительное на -ung."""
        assert self.m.detect_pos("Bildung") == "noun"

    def test_detect_pos_verb(self):
        """Глагол на -en."""
        assert self.m.detect_pos("machen") == "verb"

    def test_detect_pos_adj(self):
        """Прилагательное на -lich."""
        assert self.m.detect_pos("freundlich") == "adj"

    def test_detect_pos_noun_capital(self):
        """Немецкое существительное с заглавной буквы."""
        # "Haus" не оканчивается на adj/verb суффиксы → проверяется заглавная
        assert self.m.detect_pos("Haus") == "noun"

    def test_detect_pos_other(self):
        """Неопределяемая часть речи."""
        assert self.m.detect_pos("und") == "other"


# ═══════════════════════════════════════════════════════════════
#  Неподдерживаемые языки
# ═══════════════════════════════════════════════════════════════

class TestUnsupportedLanguage:
    """Тесты для неподдерживаемых языков."""

    def setup_method(self):
        self.m = MorphologyEngine("ja")

    def test_lemmatize_passthrough(self):
        """Для неподдерживаемых языков слово возвращается как есть."""
        assert self.m.lemmatize("テスト") == "テスト"

    def test_generate_forms_single(self):
        """Генерация форм — только сама лемма."""
        forms = self.m.generate_forms("テスト")
        assert forms == ["テスト"]

    def test_synonym_form_passthrough(self):
        """Подбор формы — синоним возвращается как есть."""
        assert self.m.find_synonym_form("foo", "bar") == "bar"

    def test_detect_pos_other(self):
        """Часть речи — other."""
        assert self.m.detect_pos("テスト") == "other"


# ═══════════════════════════════════════════════════════════════
#  Утилиты
# ═══════════════════════════════════════════════════════════════

class TestGetMorphology:
    """Тесты get_morphology singleton."""

    def test_returns_engine(self):
        """Возвращает экземпляр MorphologyEngine."""
        eng = get_morphology("en")
        assert isinstance(eng, MorphologyEngine)

    def test_cache(self):
        """Повторный вызов возвращает тот же объект."""
        e1 = get_morphology("ru")
        e2 = get_morphology("ru")
        assert e1 is e2

    def test_different_langs(self):
        """Разные языки — разные объекты."""
        en = get_morphology("en")
        de = get_morphology("de")
        assert en is not de
