"""Tests for ASR error tolerance."""

from ijaza import QuranValidator, ValidatorOptions
from ijaza.asr_tolerance import (
    get_substitution_cost,
    weighted_levenshtein,
    calculate_asr_similarity,
    remove_stutter_repetitions,
    normalize_word_boundaries,
    word_level_similarity,
    preprocess_asr_text,
)
from ijaza.normalizer import levenshtein_distance


class TestPhoneticConfusionMatrix:
    def test_identical_chars_cost_zero(self):
        assert get_substitution_cost('ب', 'ب') == 0.0

    def test_phonetic_pair_reduced_cost(self):
        cost = get_substitution_cost('ص', 'س')
        assert 0.0 < cost < 1.0
        assert cost == 0.3

    def test_unrelated_chars_full_cost(self):
        assert get_substitution_cost('ب', 'ك') == 1.0

    def test_symmetric(self):
        assert get_substitution_cost('ط', 'ت') == get_substitution_cost('ت', 'ط')

    def test_alef_variants_free(self):
        assert get_substitution_cost('ا', 'أ') == 0.0
        assert get_substitution_cost('ا', 'إ') == 0.0
        assert get_substitution_cost('ا', 'آ') == 0.0

    def test_ya_alef_maqsura_free(self):
        assert get_substitution_cost('ي', 'ى') == 0.0

    def test_ta_marbuta_ha_free(self):
        assert get_substitution_cost('ة', 'ه') == 0.0


class TestWeightedLevenshtein:
    def test_identical_strings(self):
        assert weighted_levenshtein("بسم", "بسم") == 0.0

    def test_phonetic_confusion_lower_distance(self):
        # "صراط" vs "سراط" -- Sad/Sin confusion
        weighted = weighted_levenshtein("صراط", "سراط")
        standard = levenshtein_distance("صراط", "سراط")
        assert weighted < standard

    def test_empty_strings(self):
        assert weighted_levenshtein("", "") == 0.0
        assert weighted_levenshtein("abc", "") == 3.0
        assert weighted_levenshtein("", "abc") == 3.0


class TestASRSimilarity:
    def test_identical(self):
        assert calculate_asr_similarity("بسم الله", "بسم الله") == 1.0

    def test_empty(self):
        assert calculate_asr_similarity("", "") == 1.0
        assert calculate_asr_similarity("بسم", "") == 0.0

    def test_phonetic_swap_high_similarity(self):
        # "الصراط" vs "السراط" -- common ASR confusion Sad/Sin
        sim = calculate_asr_similarity("السراط", "الصراط")
        assert sim > 0.85


class TestStutterRemoval:
    def test_removes_consecutive_duplicates(self):
        assert remove_stutter_repetitions("قل قل هو الله") == "قل هو الله"

    def test_preserves_non_duplicates(self):
        assert remove_stutter_repetitions("قل هو الله") == "قل هو الله"

    def test_handles_empty(self):
        assert remove_stutter_repetitions("") == ""

    def test_single_word(self):
        assert remove_stutter_repetitions("قل") == "قل"

    def test_multiple_stutters(self):
        assert remove_stutter_repetitions("قل قل هو هو الله") == "قل هو الله"


class TestWordBoundaryNormalization:
    def test_removes_zero_width_chars(self):
        # Zero-width space between words
        text = "بسم\u200Bالله"
        result = normalize_word_boundaries(text)
        assert "\u200B" not in result

    def test_collapses_spaces(self):
        assert normalize_word_boundaries("بسم   الله") == "بسم الله"


class TestWordLevelSimilarity:
    def test_identical(self):
        words = ["قل", "هو", "الله", "احد"]
        assert word_level_similarity(words, words) == 1.0

    def test_function_word_dropped_lenient(self):
        # ASR dropped "و" -- should still score high
        input_words = ["اتقوا", "الله", "لا", "تموتن"]
        verse_words = ["اتقوا", "الله", "و", "لا", "تموتن"]
        sim = word_level_similarity(input_words, verse_words)
        assert sim > 0.8

    def test_empty_inputs(self):
        assert word_level_similarity([], []) == 1.0
        assert word_level_similarity(["قل"], []) == 0.0
        assert word_level_similarity([], ["قل"]) == 0.0


class TestPreprocessASRText:
    def test_applies_stutter_removal(self):
        result = preprocess_asr_text("قل قل هو الله")
        assert result == "قل هو الله"

    def test_applies_boundary_normalization(self):
        result = preprocess_asr_text("بسم   الله")
        assert result == "بسم الله"


class TestValidatorWithASR:
    def test_asr_mode_backward_compatible(self):
        """ASR mode should still find exact matches."""
        validator = QuranValidator(ValidatorOptions(asr_tolerant=True))
        v = validator.get_verse(1, 1)
        assert v is not None
        result = validator.validate(v.text)
        assert result.is_valid
        assert result.match_type == 'exact'

    def test_asr_mode_finds_normalized_match(self):
        """ASR mode finds normalized matches like standard mode."""
        validator = QuranValidator(ValidatorOptions(asr_tolerant=True))
        # Simple text without diacritics for Al-Fatiha 1:1
        result = validator.validate("بسم الله الرحمن الرحيم")
        assert result.is_valid

    def test_standard_mode_unchanged(self):
        """Non-ASR mode should work the same as before."""
        validator = QuranValidator()
        v = validator.get_verse(1, 1)
        assert v is not None
        result = validator.validate(v.text)
        assert result.is_valid
        assert result.match_type == 'exact'

    def test_asr_stutter_removal(self):
        """ASR mode removes stutters before matching."""
        validator = QuranValidator(ValidatorOptions(asr_tolerant=True))
        # "بسم بسم الله الرحمن الرحيم" - stutter on first word
        result = validator.validate("بسم بسم الله الرحمن الرحيم")
        assert result.is_valid
