import Testing
@testable import SharedModels

@Suite("AnswerGrader")
struct AnswerGraderTests {

    @Test("exact match is correct")
    func exact() {
        #expect(AnswerGrader.grade(userText: "tengo", canonical: "tengo") == .correct)
        #expect(AnswerGrader.grade(userText: "Tengo", canonical: "tengo") == .correct)
        #expect(AnswerGrader.grade(userText: "  tengo  ", canonical: "tengo") == .correct)
    }

    @Test("missing accent is close")
    func missingAccent() {
        #expect(AnswerGrader.grade(userText: "esta", canonical: "está") == .close)
        #expect(AnswerGrader.grade(userText: "nino", canonical: "niño") == .close)
        #expect(AnswerGrader.grade(userText: "asi", canonical: "así") == .close)
    }

    @Test("single-char typo is close")
    func singleCharTypo() {
        // deletion
        #expect(AnswerGrader.grade(userText: "tngo", canonical: "tengo") == .close)
        // insertion
        #expect(AnswerGrader.grade(userText: "tengoo", canonical: "tengo") == .close)
        // substitution
        #expect(AnswerGrader.grade(userText: "tengu", canonical: "tengo") == .close)
    }

    @Test("two-char typo is wrong")
    func twoCharTypo() {
        #expect(AnswerGrader.grade(userText: "tngu", canonical: "tengo") == .wrong)
    }

    @Test("empty is wrong")
    func empty() {
        #expect(AnswerGrader.grade(userText: "", canonical: "tengo") == .wrong)
        #expect(AnswerGrader.grade(userText: "   ", canonical: "tengo") == .wrong)
    }

    @Test("alternates accepted")
    func alternates() {
        #expect(AnswerGrader.grade(userText: "flaca", canonical: "delgada", alternates: ["flaca"]) == .correct)
        #expect(AnswerGrader.grade(userText: "flacca", canonical: "delgada", alternates: ["flaca"]) == .close)
    }

    @Test("punctuation stripped")
    func punctuation() {
        #expect(AnswerGrader.grade(userText: "el libro.", canonical: "el libro") == .correct)
        #expect(AnswerGrader.grade(userText: "¿dónde?", canonical: "dónde") == .correct)
    }

    @Test("very different text is wrong")
    func wrong() {
        #expect(AnswerGrader.grade(userText: "hola", canonical: "tengo") == .wrong)
        #expect(AnswerGrader.grade(userText: "casa", canonical: "perro") == .wrong)
    }

    @Test("normalize produces expected output")
    func normalize() {
        #expect(AnswerGrader.normalize("  Hola  ") == "hola")
        #expect(AnswerGrader.normalize("ABC!") == "abc")
    }

    @Test("stripAccents handles common Spanish diacritics")
    func stripAccents() {
        #expect(AnswerGrader.stripAccents("niño") == "nino")
        #expect(AnswerGrader.stripAccents("está") == "esta")
        #expect(AnswerGrader.stripAccents("güero") == "guero")
    }

    @Test("levenshtein computes edit distance")
    func levenshtein() {
        #expect(AnswerGrader.levenshtein("kitten", "sitting") == 3)
        #expect(AnswerGrader.levenshtein("flaw", "lawn") == 2)
        #expect(AnswerGrader.levenshtein("abc", "abc") == 0)
        #expect(AnswerGrader.levenshtein("", "abc") == 3)
    }
}
