from inspect_evals.docvqa.docvqa import (
    _best_normalized_levenshtein_similiarity as best,
)
from inspect_evals.docvqa.docvqa import (
    _levenshtein_distance as levenshtein,
)


def test_levenshtein():
    # Basic test cases
    assert levenshtein("", "") == 0  # Empty strings
    assert levenshtein("a", "a") == 0  # Same single char
    assert levenshtein("abc", "abc") == 0  # Same string

    # Single operations
    assert levenshtein("a", "") == 1  # Single deletion
    assert levenshtein("", "a") == 1  # Single insertion
    assert levenshtein("a", "b") == 1  # Single substitution

    # Multiple operations
    assert levenshtein("kitten", "sitting") == 3  # Classic example
    assert levenshtein("sunday", "saturday") == 3  # Real words


def test_best_normalized_levenshtein_distance():
    def best_norm_lev_sim(completion, ground_truths, threshold=2.0):
        return round(best(completion, ground_truths, threshold), 3)

    # Basic cases
    assert best_norm_lev_sim("", [""]) == 1.0  # Empty strings
    assert best_norm_lev_sim("a", ["a"]) == 1.0  # Single char match
    assert best_norm_lev_sim("", ["a"]) == 0.0  # Empty vs char
    assert best_norm_lev_sim("a", ["b"]) == 0.0  # Different chars

    # Multiple correct answers
    assert (
        best_norm_lev_sim("color", ["color", "colour"]) == 1.0
    )  # Exact match with variants

    assert (
        best_norm_lev_sim("theatre", ["theater", "theatre"]) == 1.0
    )  # Regional spellings

    # Partial matches with multiple answers
    assert best_norm_lev_sim("thetre", ["theater", "theatre"]) == round(
        1 - 1 / 7, 3
    )  # One deletion

    # Case insensitivity
    assert best_norm_lev_sim("HELLO", ["hello", "hola"]) == 1.0  # All case differences

    # Length differences
    assert best_norm_lev_sim("hi", ["hello", "hey"]) == round(
        1 - 2 / 3, 3
    )  # Short vs longer options

    assert best_norm_lev_sim("hi", ["hello", "hey"], 0.5) == 0.0  # Test threshold

    assert best_norm_lev_sim("hi", ["hello", "hey"], 0.75) == round(
        1 - 2 / 3, 3
    )  # Test threshold

    # Numeric and special characters
    assert (
        best_norm_lev_sim("2nd floor", ["second floor", "2nd floor", "floor 2"]) == 1.0
    )  # Number representations

    # Common abbreviations
    assert (
        best_norm_lev_sim("dept", ["department", "dept.", "dept"]) == 1.0
    )  # Abbreviation matches

    # Multiple errors
    assert best_norm_lev_sim(
        "californa", ["california", "calif", "ca"]
    ) > best_norm_lev_sim(
        "calfrnia", ["california", "calif", "ca"]
    )  # Better partial match

    # Spaces and formatting
    assert (
        best_norm_lev_sim("new york", ["newyork", "new york", "ny"]) == 1.0
    )  # Space variations

    # Unicode and special characters
    assert best_norm_lev_sim("café", ["cafe", "café", "caffè"]) == 1.0  # Accent marks

    # Long string comparisons
    assert (
        best_norm_lev_sim(
            "mississipi river", ["mississippi river", "river mississippi"]
        )
        > 0.9
    )  # Minor spelling error

    # Completely different strings
    assert best_norm_lev_sim("kiwi", ["banana", "orange"]) == 0.0  # No similarity
