import Testing
@testable import SharedModels

@Suite("EnglishConjugator")
struct EnglishConjugatorTests {

    // MARK: - haber (to have) — irregular English verb

    @Test("haber present: I have / you have / he/she has")
    func haberPresent() {
        #expect(t("to have", "ind_presente", 0) == "I have")
        #expect(t("to have", "ind_presente", 1) == "you have")
        #expect(t("to have", "ind_presente", 2) == "he/she has")
        #expect(t("to have", "ind_presente", 3) == "we have")
        #expect(t("to have", "ind_presente", 5) == "they have")
    }

    @Test("haber preterite: I had")
    func haberPreterite() {
        #expect(t("to have", "ind_preterito", 0) == "I had")
        #expect(t("to have", "ind_preterito", 2) == "he/she had")
    }

    @Test("haber future: I will have")
    func haberFuture() {
        #expect(t("to have", "ind_futuro", 0) == "I will have")
        #expect(t("to have", "ind_futuro", 3) == "we will have")
    }

    @Test("haber conditional: I would have")
    func haberConditional() {
        #expect(t("to have", "cond_presente", 0) == "I would have")
    }

    @Test("haber present perfect: I have had / he/she has had")
    func haberPresentPerfect() {
        #expect(t("to have", "ind_perfecto", 0) == "I have had")
        #expect(t("to have", "ind_perfecto", 2) == "he/she has had")
    }

    // MARK: - ir (to go) — irregular English verb

    @Test("ir present: I go / he/she goes")
    func irPresent() {
        #expect(t("to go", "ind_presente", 0) == "I go")
        #expect(t("to go", "ind_presente", 2) == "he/she goes")
        #expect(t("to go", "ind_presente", 5) == "they go")
    }

    @Test("ir preterite: I went")
    func irPreterite() {
        #expect(t("to go", "ind_preterito", 0) == "I went")
        #expect(t("to go", "ind_preterito", 2) == "he/she went")
    }

    @Test("ir imperfect: I used to go")
    func irImperfect() {
        #expect(t("to go", "ind_imperfecto", 0) == "I used to go")
    }

    @Test("ir present perfect: I have gone")
    func irPresentPerfect() {
        #expect(t("to go", "ind_perfecto", 0) == "I have gone")
        #expect(t("to go", "ind_perfecto", 2) == "he/she has gone")
    }

    // MARK: - ser (to be) — most irregular English verb

    @Test("ser present: he/she is")
    func serPresent() {
        #expect(t("to be", "ind_presente", 2) == "he/she is")
    }

    @Test("ser preterite: I was/were")
    func serPreterite() {
        #expect(t("to be", "ind_preterito", 0) == "I was/were")
    }

    @Test("ser present perfect: I have been")
    func serPresentPerfect() {
        #expect(t("to be", "ind_perfecto", 0) == "I have been")
    }

    // MARK: - hablar (to speak)

    @Test("hablar present: I speak / he/she speaks")
    func hablarPresent() {
        #expect(t("to speak", "ind_presente", 0) == "I speak")
        #expect(t("to speak", "ind_presente", 2) == "he/she speaks")
    }

    @Test("hablar preterite: I spoke")
    func hablarPreterite() {
        #expect(t("to speak", "ind_preterito", 0) == "I spoke")
    }

    @Test("hablar present perfect: I have spoken")
    func hablarPresentPerfect() {
        #expect(t("to speak", "ind_perfecto", 0) == "I have spoken")
    }

    // MARK: - comer (to eat)

    @Test("comer preterite: I ate")
    func comerPreterite() {
        #expect(t("to eat", "ind_preterito", 0) == "I ate")
    }

    @Test("comer present perfect: I have eaten")
    func comerPresentPerfect() {
        #expect(t("to eat", "ind_perfecto", 0) == "I have eaten")
    }

    // MARK: - vivir (to live) — regular English verb

    @Test("vivir present: I live / he/she lives")
    func vivirPresent() {
        #expect(t("to live", "ind_presente", 0) == "I live")
        #expect(t("to live", "ind_presente", 2) == "he/she lives")
    }

    @Test("vivir preterite: I lived")
    func vivirPreterite() {
        #expect(t("to live", "ind_preterito", 0) == "I lived")
    }

    // MARK: - abatir (to knock down) — multi-word verb

    @Test("abatir present: I knock down / he/she knocks down")
    func abatirPresent() {
        #expect(t("to knock down", "ind_presente", 0) == "I knock down")
        #expect(t("to knock down", "ind_presente", 2) == "he/she knocks down")
    }

    @Test("abatir conditional: I would knock down")
    func abatirConditional() {
        #expect(t("to knock down", "cond_presente", 0) == "I would knock down")
        #expect(t("to knock down", "cond_presente", 2) == "he/she would knock down")
    }

    @Test("abatir preterite: I knocked down")
    func abatirPreterite() {
        #expect(t("to knock down", "ind_preterito", 0) == "I knocked down")
    }

    // MARK: - Conditional

    @Test("conditional: I would speak")
    func conditional() {
        #expect(t("to speak", "cond_presente", 0) == "I would speak")
        #expect(t("to speak", "cond_presente", 2) == "he/she would speak")
    }

    @Test("conditional perfect: I would have gone")
    func conditionalPerfect() {
        #expect(t("to go", "cond_perfecto", 0) == "I would have gone")
    }

    // MARK: - Subjunctive

    @Test("present subjunctive: that I speak")
    func presentSubjunctive() {
        #expect(t("to speak", "subj_presente", 0) == "that I speak")
        #expect(t("to speak", "subj_presente", 2) == "that he/she speak")
    }

    @Test("imperfect subjunctive (ra): that I would speak")
    func imperfectSubjunctive1() {
        #expect(t("to speak", "subj_imperfecto_1", 0) == "that I would speak")
    }

    @Test("imperfect subjunctive (se): that I would speak")
    func imperfectSubjunctive2() {
        #expect(t("to speak", "subj_imperfecto_2", 0) == "that I would speak")
    }

    @Test("subjunctive perfect: that I have spoken")
    func subjunctivePerfect() {
        #expect(t("to speak", "subj_perfecto", 0) == "that I have spoken")
        #expect(t("to speak", "subj_perfecto", 2) == "that he/she has spoken")
    }

    @Test("subjunctive pluperfect: that I had gone")
    func subjunctivePluperfect() {
        #expect(t("to go", "subj_pluscuamperfecto_1", 0) == "that I had gone")
        #expect(t("to go", "subj_pluscuamperfecto_2", 0) == "that I had gone")
    }

    @Test("subjunctive future: that I will speak")
    func subjunctiveFuture() {
        #expect(t("to speak", "subj_futuro", 0) == "that I will speak")
    }

    @Test("subjunctive future perfect: that I will have spoken")
    func subjunctiveFuturePerfect() {
        #expect(t("to speak", "subj_futuro_perfecto", 0) == "that I will have spoken")
    }

    // MARK: - Imperative

    @Test("imperative affirmative")
    func imperativeAffirmative() {
        #expect(t("to speak", "imp_afirmativo", 1) == "speak!")
        #expect(t("to speak", "imp_afirmativo", 3) == "let's speak!")
    }

    @Test("imperative negative")
    func imperativeNegative() {
        #expect(t("to speak", "imp_negativo", 1) == "don't speak")
    }

    // MARK: - Compound indicative tenses

    @Test("pluperfect: I had spoken")
    func pluperfect() {
        #expect(t("to speak", "ind_pluscuamperfecto", 0) == "I had spoken")
        #expect(t("to go", "ind_pluscuamperfecto", 0) == "I had gone")
    }

    @Test("future perfect: I will have spoken")
    func futurePerfect() {
        #expect(t("to speak", "ind_futuro_perfecto", 0) == "I will have spoken")
    }

    @Test("preterite anterior: I had spoken (same as pluperfect in English)")
    func preteriteAnterior() {
        #expect(t("to speak", "ind_preterito_anterior", 0) == "I had spoken")
    }

    // MARK: - Edge cases

    @Test("empty english returns empty string")
    func emptyEnglish() {
        #expect(t("", "ind_presente", 0) == "")
        #expect(t("to ", "ind_presente", 0) == "")
    }

    @Test("unknown tense falls back to pronoun + base")
    func unknownTense() {
        #expect(t("to speak", "some_future_tense", 0) == "I speak")
    }

    @Test("3rd person present: study → studies")
    func thirdPersonYRule() {
        #expect(t("to study", "ind_presente", 2) == "he/she studies")
    }

    @Test("3rd person present: play → plays")
    func thirdPersonVowelY() {
        #expect(t("to play", "ind_presente", 2) == "he/she plays")
    }

    @Test("3rd person present: watch → watches")
    func thirdPersonChRule() {
        #expect(t("to watch", "ind_presente", 2) == "he/she watches")
    }

    @Test("past regular: carry → carried")
    func pastYRule() {
        #expect(t("to carry", "ind_preterito", 0) == "I carried")
    }

    // MARK: - Helper

    private func t(_ english: String, _ tenseId: String, _ personIndex: Int) -> String {
        EnglishConjugator.translate(english: english, tenseId: tenseId, personIndex: personIndex)
    }
}
