// morphology-grc.el - Ancient Greek morphology for the NLG engine.
//
// Implements polytonic Ancient Greek verb conjugation, noun declension, and
// the definite article.  Designed as a companion to morphology.el and called
// by the engine when the language profile code is "grc".
//
// Language profile: code=grc, name=Ancient Greek, morph_type=fusional,
//   word_order=SOV, question_strategy=particle, script=greek, family=hellenic.
//
// Typology note: Ancient Greek is a heavily inflected synthetic language with
// rich morphophonology.  Nouns carry gender, case, and number in fused endings.
// Verbs encode tense, aspect, voice, mood, person, and number.  The augment
// (ε-) marks past indicative.  All polytonic diacritics are preserved in
// string literals; comparisons use exact Unicode equality.
//
// Verb conjugation covered:
//   Tenses:    present, imperfect, aorist, future
//   Persons:   first/second/third × singular/plural (slots 0-5)
//   Class:     thematic (-ω) verbs
//   Irregulars: εἰναι (be), ἔχειν (have), λέγειν (say), ὁράω (see),
//               ἔρχεσθαι (come/go)
//   Canonical map: "be" -> "εἰναι"
//
// Noun declension covered:
//   Cases:       nominative, accusative, genitive, dative, vocative
//   Declensions: 1st (-α/-η fem), 2nd masc (-ος), 2nd neut (-ον), 3rd (base)
//
// Article: full 24-form table for ὁ/ἡ/τό (gender × case × number).
//
// Depends on: morphology.el (str_ends_with, str_len, str_slice, str_eq)

// ── String helpers ─────────────────────────────────────────────────────────────

fn grc_str_ends(s: String, suf: String) -> Bool {
    return str_ends_with(s, suf)
}

fn grc_str_drop_last(s: String, n: Int) -> String {
    let len: Int = str_len(s)
    if n >= len {
        return ""
    }
    return str_slice(s, 0, len - n)
}

fn grc_str_last_char(s: String) -> String {
    let n: Int = str_len(s)
    if n == 0 {
        return ""
    }
    return str_slice(s, n - 1, n)
}

fn grc_str_last2(s: String) -> String {
    let n: Int = str_len(s)
    if n < 2 {
        return s
    }
    return str_slice(s, n - 2, n)
}

fn grc_str_last3(s: String) -> String {
    let n: Int = str_len(s)
    if n < 3 {
        return s
    }
    return str_slice(s, n - 3, n)
}

// ── Person/number slot ─────────────────────────────────────────────────────────
//
// Maps person × number to a 0-based index used in all paradigm tables.
//   0 = 1st singular  (ἐγώ)
//   1 = 2nd singular  (σύ)
//   2 = 3rd singular  (αὐτός/αὐτή/αὐτό)
//   3 = 1st plural    (ἡμεῖς)
//   4 = 2nd plural    (ὑμεῖς)
//   5 = 3rd plural    (αὐτοί)
//
// Dual number is not handled; dual inputs fall through to plural.

fn grc_slot(person: String, number: String) -> Int {
    if str_eq(person, "first") {
        if str_eq(number, "singular") { return 0 }
        return 3
    }
    if str_eq(person, "second") {
        if str_eq(number, "singular") { return 1 }
        return 4
    }
    // third
    if str_eq(number, "singular") { return 2 }
    return 5
}

// ── Canonical verb mapping ─────────────────────────────────────────────────────
//
// The semantic layer may pass English canonical labels.  Map these to the
// Ancient Greek infinitive (or dictionary citation form) before conjugation.

fn grc_map_canonical(verb: String) -> String {
    if str_eq(verb, "be")     { return "εἰναι" }
    if str_eq(verb, "have")   { return "ἔχειν" }
    if str_eq(verb, "say")    { return "λέγειν" }
    if str_eq(verb, "see")    { return "ὁράω" }
    if str_eq(verb, "come")   { return "ἔρχεσθαι" }
    if str_eq(verb, "go")     { return "ἔρχεσθαι" }
    if str_eq(verb, "know")   { return "γιγνώσκειν" }
    if str_eq(verb, "write")  { return "γράφειν" }
    if str_eq(verb, "hear")   { return "ἀκούειν" }
    if str_eq(verb, "want")   { return "βούλεσθαι" }
    if str_eq(verb, "do")     { return "ποιεῖν" }
    if str_eq(verb, "make")   { return "ποιεῖν" }
    return verb
}

// ── Irregular: εἰναι (to be) ──────────────────────────────────────────────────
//
// Present indicative active: εἰμί εἶ ἐστί ἐσμέν ἐστέ εἰσί
// Imperfect:                 ἦν   ἦσθα ἦν   ἦμεν  ἦτε  ἦσαν
// Future:                    ἔσομαι ἔσῃ ἔσται ἐσόμεθα ἔσεσθε ἔσονται
// Aorist: no aorist of εἰμί; use imperfect as fallback

fn grc_einai_present(slot: Int) -> String {
    if slot == 0 { return "εἰμί" }
    if slot == 1 { return "εἶ" }
    if slot == 2 { return "ἐστί" }
    if slot == 3 { return "ἐσμέν" }
    if slot == 4 { return "ἐστέ" }
    return "εἰσί"
}

fn grc_einai_imperfect(slot: Int) -> String {
    if slot == 0 { return "ἦν" }
    if slot == 1 { return "ἦσθα" }
    if slot == 2 { return "ἦν" }
    if slot == 3 { return "ἦμεν" }
    if slot == 4 { return "ἦτε" }
    return "ἦσαν"
}

fn grc_einai_future(slot: Int) -> String {
    if slot == 0 { return "ἔσομαι" }
    if slot == 1 { return "ἔσῃ" }
    if slot == 2 { return "ἔσται" }
    if slot == 3 { return "ἐσόμεθα" }
    if slot == 4 { return "ἔσεσθε" }
    return "ἔσονται"
}

// ── Irregular: ἔχειν (to have) ────────────────────────────────────────────────
//
// Present:   ἔχω ἔχεις ἔχει ἔχομεν ἔχετε ἔχουσι
// Imperfect: εἶχον εἶχες εἶχε εἴχομεν εἴχετε εἶχον
// Aorist:    ἔσχον ἔσχες ἔσχε ἔσχομεν ἔσχετε ἔσχον
// Future:    ἕξω ἕξεις ἕξει ἕξομεν ἕξετε ἕξουσι

fn grc_echein_present(slot: Int) -> String {
    if slot == 0 { return "ἔχω" }
    if slot == 1 { return "ἔχεις" }
    if slot == 2 { return "ἔχει" }
    if slot == 3 { return "ἔχομεν" }
    if slot == 4 { return "ἔχετε" }
    return "ἔχουσι"
}

fn grc_echein_imperfect(slot: Int) -> String {
    if slot == 0 { return "εἶχον" }
    if slot == 1 { return "εἶχες" }
    if slot == 2 { return "εἶχε" }
    if slot == 3 { return "εἴχομεν" }
    if slot == 4 { return "εἴχετε" }
    return "εἶχον"
}

fn grc_echein_aorist(slot: Int) -> String {
    if slot == 0 { return "ἔσχον" }
    if slot == 1 { return "ἔσχες" }
    if slot == 2 { return "ἔσχε" }
    if slot == 3 { return "ἔσχομεν" }
    if slot == 4 { return "ἔσχετε" }
    return "ἔσχον"
}

fn grc_echein_future(slot: Int) -> String {
    if slot == 0 { return "ἕξω" }
    if slot == 1 { return "ἕξεις" }
    if slot == 2 { return "ἕξει" }
    if slot == 3 { return "ἕξομεν" }
    if slot == 4 { return "ἕξετε" }
    return "ἕξουσι"
}

// ── Irregular: λέγειν (to say) ────────────────────────────────────────────────
//
// Present:   λέγω λέγεις λέγει λέγομεν λέγετε λέγουσι
// Imperfect: ἔλεγον ἔλεγες ἔλεγε ἐλέγομεν ἐλέγετε ἔλεγον
// Aorist:    εἶπον εἶπες εἶπε εἴπομεν εἴπετε εἶπον
// Future:    λέξω λέξεις λέξει λέξομεν λέξετε λέξουσι

fn grc_legein_present(slot: Int) -> String {
    if slot == 0 { return "λέγω" }
    if slot == 1 { return "λέγεις" }
    if slot == 2 { return "λέγει" }
    if slot == 3 { return "λέγομεν" }
    if slot == 4 { return "λέγετε" }
    return "λέγουσι"
}

fn grc_legein_imperfect(slot: Int) -> String {
    if slot == 0 { return "ἔλεγον" }
    if slot == 1 { return "ἔλεγες" }
    if slot == 2 { return "ἔλεγε" }
    if slot == 3 { return "ἐλέγομεν" }
    if slot == 4 { return "ἐλέγετε" }
    return "ἔλεγον"
}

fn grc_legein_aorist(slot: Int) -> String {
    if slot == 0 { return "εἶπον" }
    if slot == 1 { return "εἶπες" }
    if slot == 2 { return "εἶπε" }
    if slot == 3 { return "εἴπομεν" }
    if slot == 4 { return "εἴπετε" }
    return "εἶπον"
}

fn grc_legein_future(slot: Int) -> String {
    if slot == 0 { return "λέξω" }
    if slot == 1 { return "λέξεις" }
    if slot == 2 { return "λέξει" }
    if slot == 3 { return "λέξομεν" }
    if slot == 4 { return "λέξετε" }
    return "λέξουσι"
}

// ── Irregular: ὁράω (to see) ──────────────────────────────────────────────────
//
// Present:   ὁράω ὁράς ὁρᾷ ὁρῶμεν ὁρᾶτε ὁρῶσι
// Imperfect: ἑώρων ἑώρας ἑώρα ἑωρῶμεν ἑωρᾶτε ἑώρων
// Aorist:    εἶδον εἶδες εἶδε εἴδομεν εἴδετε εἶδον
// Future:    ὄψομαι ὄψῃ ὄψεται ὀψόμεθα ὄψεσθε ὄψονται

fn grc_horao_present(slot: Int) -> String {
    if slot == 0 { return "ὁράω" }
    if slot == 1 { return "ὁράς" }
    if slot == 2 { return "ὁρᾷ" }
    if slot == 3 { return "ὁρῶμεν" }
    if slot == 4 { return "ὁρᾶτε" }
    return "ὁρῶσι"
}

fn grc_horao_imperfect(slot: Int) -> String {
    if slot == 0 { return "ἑώρων" }
    if slot == 1 { return "ἑώρας" }
    if slot == 2 { return "ἑώρα" }
    if slot == 3 { return "ἑωρῶμεν" }
    if slot == 4 { return "ἑωρᾶτε" }
    return "ἑώρων"
}

fn grc_horao_aorist(slot: Int) -> String {
    if slot == 0 { return "εἶδον" }
    if slot == 1 { return "εἶδες" }
    if slot == 2 { return "εἶδε" }
    if slot == 3 { return "εἴδομεν" }
    if slot == 4 { return "εἴδετε" }
    return "εἶδον"
}

fn grc_horao_future(slot: Int) -> String {
    if slot == 0 { return "ὄψομαι" }
    if slot == 1 { return "ὄψῃ" }
    if slot == 2 { return "ὄψεται" }
    if slot == 3 { return "ὀψόμεθα" }
    if slot == 4 { return "ὄψεσθε" }
    return "ὄψονται"
}

// ── Irregular: ἔρχεσθαι (to come / to go) ────────────────────────────────────
//
// Present:   ἔρχομαι ἔρχῃ ἔρχεται ἐρχόμεθα ἔρχεσθε ἔρχονται
// Imperfect: ἠρχόμην ἤρχου ἤρχετο ἠρχόμεθα ἤρχεσθε ἤρχοντο
// Aorist:    ἦλθον ἦλθες ἦλθε ἤλθομεν ἤλθετε ἦλθον
// Future:    εἶμι εἶ εἶσι ἴμεν ἴτε ἴασι

fn grc_erchesthai_present(slot: Int) -> String {
    if slot == 0 { return "ἔρχομαι" }
    if slot == 1 { return "ἔρχῃ" }
    if slot == 2 { return "ἔρχεται" }
    if slot == 3 { return "ἐρχόμεθα" }
    if slot == 4 { return "ἔρχεσθε" }
    return "ἔρχονται"
}

fn grc_erchesthai_imperfect(slot: Int) -> String {
    if slot == 0 { return "ἠρχόμην" }
    if slot == 1 { return "ἤρχου" }
    if slot == 2 { return "ἤρχετο" }
    if slot == 3 { return "ἠρχόμεθα" }
    if slot == 4 { return "ἤρχεσθε" }
    return "ἤρχοντο"
}

fn grc_erchesthai_aorist(slot: Int) -> String {
    if slot == 0 { return "ἦλθον" }
    if slot == 1 { return "ἦλθες" }
    if slot == 2 { return "ἦλθε" }
    if slot == 3 { return "ἤλθομεν" }
    if slot == 4 { return "ἤλθετε" }
    return "ἦλθον"
}

fn grc_erchesthai_future(slot: Int) -> String {
    if slot == 0 { return "εἶμι" }
    if slot == 1 { return "εἶ" }
    if slot == 2 { return "εἶσι" }
    if slot == 3 { return "ἴμεν" }
    if slot == 4 { return "ἴτε" }
    return "ἴασι"
}

// ── Thematic (-ω) present active endings ──────────────────────────────────────
//
// Slot:  0    1      2     3       4      5
//        -ω   -εις   -ει   -ομεν   -ετε   -ουσι
//
// These are attached to the present stem.

fn grc_thematic_present_ending(slot: Int) -> String {
    if slot == 0 { return "ω" }
    if slot == 1 { return "εις" }
    if slot == 2 { return "ει" }
    if slot == 3 { return "ομεν" }
    if slot == 4 { return "ετε" }
    return "ουσι"
}

// ── Thematic imperfect active endings ─────────────────────────────────────────
//
// Imperfect = augment (ἐ-) + stem + secondary endings
// Slot:  0     1     2    3       4      5
//        -ον   -ες   -ε   -ομεν   -ετε   -ον

fn grc_thematic_imperfect_ending(slot: Int) -> String {
    if slot == 0 { return "ον" }
    if slot == 1 { return "ες" }
    if slot == 2 { return "ε" }
    if slot == 3 { return "ομεν" }
    if slot == 4 { return "ετε" }
    return "ον"
}

// ── Thematic future active endings ────────────────────────────────────────────
//
// Future = stem + σ + thematic vowel + primary endings.
// For most -ω verbs: stem + σ serves as the future stem, then present endings.
// Slot:  0     1      2     3       4      5
//        -σω   -σεις  -σει  -σομεν  -σετε  -σουσι

fn grc_thematic_future_ending(slot: Int) -> String {
    if slot == 0 { return "σω" }
    if slot == 1 { return "σεις" }
    if slot == 2 { return "σει" }
    if slot == 3 { return "σομεν" }
    if slot == 4 { return "σετε" }
    return "σουσι"
}

// ── Weak (first) aorist active endings ────────────────────────────────────────
//
// Weak aorist = augment (ἐ-) + stem + σ + aorist endings
// Slot:  0      1      2     3        4       5
//        -σα    -σας   -σε   -σαμεν   -σατε   -σαν

fn grc_weak_aorist_ending(slot: Int) -> String {
    if slot == 0 { return "σα" }
    if slot == 1 { return "σας" }
    if slot == 2 { return "σε" }
    if slot == 3 { return "σαμεν" }
    if slot == 4 { return "σατε" }
    return "σαν"
}

// ── Stem extraction ────────────────────────────────────────────────────────────
//
// Strip the citation-form ending to recover the present stem.
//   -ειν  -> strip 3 chars (λύειν -> λύ-)
//   -ω    -> strip 1 char  (λύω -> λύ-)
//   -αω   -> strip 2 chars (ὁράω -> ὁρ-; handled as irregular above)
//   -εω   -> strip 2 chars (contracted -εω verbs)
//   otherwise: return as-is (already a stem or unrecognised form)

fn grc_present_stem(verb: String) -> String {
    if grc_str_ends(verb, "ειν") {
        return grc_str_drop_last(verb, 3)
    }
    if grc_str_ends(verb, "αω") {
        return grc_str_drop_last(verb, 2)
    }
    if grc_str_ends(verb, "εω") {
        return grc_str_drop_last(verb, 2)
    }
    if grc_str_ends(verb, "ω") {
        return grc_str_drop_last(verb, 1)
    }
    return verb
}

// ── grc_conjugate: main conjugation entry point ───────────────────────────────
//
// verb:   Greek infinitive/citation form or English canonical label
// tense:  "present" | "imperfect" | "aorist" | "future"
// person: "first" | "second" | "third"
// number: "singular" | "plural"
//
// Returns the inflected form.  Falls back to the citation form for unknown
// tenses or unrecognised verbs rather than crashing.

fn grc_conjugate(verb: String, tense: String, person: String, number: String) -> String {
    let v: String = grc_map_canonical(verb)
    let slot: Int = grc_slot(person, number)

    // ── Irregulars ────────────────────────────────────────────────────────────

    if str_eq(v, "εἰναι") {
        if str_eq(tense, "present")   { return grc_einai_present(slot) }
        if str_eq(tense, "imperfect") { return grc_einai_imperfect(slot) }
        if str_eq(tense, "aorist")    { return grc_einai_imperfect(slot) }
        if str_eq(tense, "future")    { return grc_einai_future(slot) }
        return v
    }

    if str_eq(v, "ἔχειν") {
        if str_eq(tense, "present")   { return grc_echein_present(slot) }
        if str_eq(tense, "imperfect") { return grc_echein_imperfect(slot) }
        if str_eq(tense, "aorist")    { return grc_echein_aorist(slot) }
        if str_eq(tense, "future")    { return grc_echein_future(slot) }
        return v
    }

    if str_eq(v, "λέγειν") {
        if str_eq(tense, "present")   { return grc_legein_present(slot) }
        if str_eq(tense, "imperfect") { return grc_legein_imperfect(slot) }
        if str_eq(tense, "aorist")    { return grc_legein_aorist(slot) }
        if str_eq(tense, "future")    { return grc_legein_future(slot) }
        return v
    }

    if str_eq(v, "ὁράω") {
        if str_eq(tense, "present")   { return grc_horao_present(slot) }
        if str_eq(tense, "imperfect") { return grc_horao_imperfect(slot) }
        if str_eq(tense, "aorist")    { return grc_horao_aorist(slot) }
        if str_eq(tense, "future")    { return grc_horao_future(slot) }
        return v
    }

    if str_eq(v, "ἔρχεσθαι") {
        if str_eq(tense, "present")   { return grc_erchesthai_present(slot) }
        if str_eq(tense, "imperfect") { return grc_erchesthai_imperfect(slot) }
        if str_eq(tense, "aorist")    { return grc_erchesthai_aorist(slot) }
        if str_eq(tense, "future")    { return grc_erchesthai_future(slot) }
        return v
    }

    // ── Regular thematic conjugation ──────────────────────────────────────────

    let stem: String = grc_present_stem(v)

    if str_eq(tense, "present") {
        return stem + grc_thematic_present_ending(slot)
    }

    if str_eq(tense, "imperfect") {
        // Augment: prefix ἐ- to the stem
        return "ἐ" + stem + grc_thematic_imperfect_ending(slot)
    }

    if str_eq(tense, "future") {
        return stem + grc_thematic_future_ending(slot)
    }

    if str_eq(tense, "aorist") {
        // Weak (sigmatic) aorist: ἐ- + stem + σ endings
        return "ἐ" + stem + grc_weak_aorist_ending(slot)
    }

    // Unknown tense: return citation form unchanged
    return v
}

// ── Declension detection ───────────────────────────────────────────────────────
//
// Infer Greek declension class from the nominative singular ending.
//
//   ends in -ος  -> 2nd declension masculine
//   ends in -ον  -> 2nd declension neuter
//   ends in -α   -> 1st declension feminine (alpha-stem)
//   ends in -η   -> 1st declension feminine (eta-stem)
//   otherwise    -> 3rd declension (consonant stem; too varied for full tables)

fn grc_declension(noun: String) -> String {
    if grc_str_ends(noun, "ος") { return "2m" }
    if grc_str_ends(noun, "ον") { return "2n" }
    if grc_str_ends(noun, "α")  { return "1a" }
    if grc_str_ends(noun, "η")  { return "1e" }
    return "3"
}

// ── 2nd declension masculine: -ος nouns ──────────────────────────────────────
//
// Stem: remove -ος (2 chars)
// Singular: nom -ος  gen -ου  dat -ῳ   acc -ον  voc -ε
// Plural:   nom -οι  gen -ων  dat -οις acc -ους voc -οι

fn grc_decline_2m(stem: String, gram_case: String, number: String) -> String {
    if str_eq(number, "singular") {
        if str_eq(gram_case, "nominative") { return stem + "ος" }
        if str_eq(gram_case, "genitive")   { return stem + "ου" }
        if str_eq(gram_case, "dative")     { return stem + "ῳ" }
        if str_eq(gram_case, "accusative") { return stem + "ον" }
        if str_eq(gram_case, "vocative")   { return stem + "ε" }
        return stem + "ος"
    }
    // plural
    if str_eq(gram_case, "nominative") { return stem + "οι" }
    if str_eq(gram_case, "genitive")   { return stem + "ων" }
    if str_eq(gram_case, "dative")     { return stem + "οις" }
    if str_eq(gram_case, "accusative") { return stem + "ους" }
    if str_eq(gram_case, "vocative")   { return stem + "οι" }
    return stem + "οι"
}

// ── 2nd declension neuter: -ον nouns ─────────────────────────────────────────
//
// Stem: remove -ον (2 chars)
// Singular: nom/acc/voc -ον  gen -ου  dat -ῳ
// Plural:   nom/acc/voc -α   gen -ων  dat -οις

fn grc_decline_2n(stem: String, gram_case: String, number: String) -> String {
    if str_eq(number, "singular") {
        if str_eq(gram_case, "nominative") { return stem + "ον" }
        if str_eq(gram_case, "genitive")   { return stem + "ου" }
        if str_eq(gram_case, "dative")     { return stem + "ῳ" }
        if str_eq(gram_case, "accusative") { return stem + "ον" }
        if str_eq(gram_case, "vocative")   { return stem + "ον" }
        return stem + "ον"
    }
    // plural
    if str_eq(gram_case, "nominative") { return stem + "α" }
    if str_eq(gram_case, "genitive")   { return stem + "ων" }
    if str_eq(gram_case, "dative")     { return stem + "οις" }
    if str_eq(gram_case, "accusative") { return stem + "α" }
    if str_eq(gram_case, "vocative")   { return stem + "α" }
    return stem + "α"
}

// ── 1st declension feminine: alpha-stem (-α) nouns ───────────────────────────
//
// Stem: remove -α (1 char)
// Singular: nom -α   gen -ας  dat -ᾳ   acc -αν  voc -α
// Plural:   nom -αι  gen -ων  dat -αις acc -ας  voc -αι

fn grc_decline_1a(stem: String, gram_case: String, number: String) -> String {
    if str_eq(number, "singular") {
        if str_eq(gram_case, "nominative") { return stem + "α" }
        if str_eq(gram_case, "genitive")   { return stem + "ας" }
        if str_eq(gram_case, "dative")     { return stem + "ᾳ" }
        if str_eq(gram_case, "accusative") { return stem + "αν" }
        if str_eq(gram_case, "vocative")   { return stem + "α" }
        return stem + "α"
    }
    // plural
    if str_eq(gram_case, "nominative") { return stem + "αι" }
    if str_eq(gram_case, "genitive")   { return stem + "ων" }
    if str_eq(gram_case, "dative")     { return stem + "αις" }
    if str_eq(gram_case, "accusative") { return stem + "ας" }
    if str_eq(gram_case, "vocative")   { return stem + "αι" }
    return stem + "αι"
}

// ── 1st declension feminine: eta-stem (-η) nouns ─────────────────────────────
//
// Stem: remove -η (1 char)
// Singular: nom -η   gen -ης  dat -ῃ   acc -ην  voc -η
// Plural:   nom -αι  gen -ων  dat -αις acc -ας  voc -αι

fn grc_decline_1e(stem: String, gram_case: String, number: String) -> String {
    if str_eq(number, "singular") {
        if str_eq(gram_case, "nominative") { return stem + "η" }
        if str_eq(gram_case, "genitive")   { return stem + "ης" }
        if str_eq(gram_case, "dative")     { return stem + "ῃ" }
        if str_eq(gram_case, "accusative") { return stem + "ην" }
        if str_eq(gram_case, "vocative")   { return stem + "η" }
        return stem + "η"
    }
    // plural (same as alpha-stem in the plural)
    if str_eq(gram_case, "nominative") { return stem + "αι" }
    if str_eq(gram_case, "genitive")   { return stem + "ων" }
    if str_eq(gram_case, "dative")     { return stem + "αις" }
    if str_eq(gram_case, "accusative") { return stem + "ας" }
    if str_eq(gram_case, "vocative")   { return stem + "αι" }
    return stem + "αι"
}

// ── grc_decline: main declension entry point ──────────────────────────────────
//
// noun:      nominative singular Greek noun (e.g. "λόγος", "ἔργον", "χώρα")
// gram_case: "nominative" | "accusative" | "genitive" | "dative" | "vocative"
// number:    "singular" | "plural"
//
// 3rd declension consonant stems are too unpredictable without a full lexicon;
// for those the nominative is returned unchanged as a safe fallback.

fn grc_decline(noun: String, gram_case: String, number: String) -> String {
    let decl: String = grc_declension(noun)

    if str_eq(decl, "2m") {
        let stem: String = grc_str_drop_last(noun, 2)
        return grc_decline_2m(stem, gram_case, number)
    }

    if str_eq(decl, "2n") {
        let stem: String = grc_str_drop_last(noun, 2)
        return grc_decline_2n(stem, gram_case, number)
    }

    if str_eq(decl, "1a") {
        let stem: String = grc_str_drop_last(noun, 1)
        return grc_decline_1a(stem, gram_case, number)
    }

    if str_eq(decl, "1e") {
        let stem: String = grc_str_drop_last(noun, 1)
        return grc_decline_1e(stem, gram_case, number)
    }

    // 3rd declension: return the base form unchanged
    return noun
}

// ── grc_article: definite article ────────────────────────────────────────────
//
// The Ancient Greek definite article ὁ/ἡ/τό is fully declined for gender,
// case, and number.  There is no indefinite article.
//
// gender:    "masculine" | "feminine" | "neuter"
// gram_case: "nominative" | "accusative" | "genitive" | "dative" | "vocative"
// number:    "singular" | "plural"
//
//                Masc    Fem     Neut
// Nom sg:        ὁ       ἡ       τό
// Gen sg:        τοῦ     τῆς     τοῦ
// Dat sg:        τῷ      τῇ      τῷ
// Acc sg:        τόν     τήν     τό
// Voc sg:        (none; ὦ used as exclamatory particle, not article)
// Nom pl:        οἱ      αἱ      τά
// Gen pl:        τῶν     τῶν     τῶν
// Dat pl:        τοῖς    ταῖς    τοῖς
// Acc pl:        τούς    τάς     τά
// Voc pl:        (same as nom pl in practice)

fn grc_article_masculine(gram_case: String, number: String) -> String {
    if str_eq(number, "singular") {
        if str_eq(gram_case, "nominative") { return "ὁ" }
        if str_eq(gram_case, "genitive")   { return "τοῦ" }
        if str_eq(gram_case, "dative")     { return "τῷ" }
        if str_eq(gram_case, "accusative") { return "τόν" }
        if str_eq(gram_case, "vocative")   { return "ὁ" }
        return "ὁ"
    }
    // plural
    if str_eq(gram_case, "nominative") { return "οἱ" }
    if str_eq(gram_case, "genitive")   { return "τῶν" }
    if str_eq(gram_case, "dative")     { return "τοῖς" }
    if str_eq(gram_case, "accusative") { return "τούς" }
    if str_eq(gram_case, "vocative")   { return "οἱ" }
    return "οἱ"
}

fn grc_article_feminine(gram_case: String, number: String) -> String {
    if str_eq(number, "singular") {
        if str_eq(gram_case, "nominative") { return "ἡ" }
        if str_eq(gram_case, "genitive")   { return "τῆς" }
        if str_eq(gram_case, "dative")     { return "τῇ" }
        if str_eq(gram_case, "accusative") { return "τήν" }
        if str_eq(gram_case, "vocative")   { return "ἡ" }
        return "ἡ"
    }
    // plural
    if str_eq(gram_case, "nominative") { return "αἱ" }
    if str_eq(gram_case, "genitive")   { return "τῶν" }
    if str_eq(gram_case, "dative")     { return "ταῖς" }
    if str_eq(gram_case, "accusative") { return "τάς" }
    if str_eq(gram_case, "vocative")   { return "αἱ" }
    return "αἱ"
}

fn grc_article_neuter(gram_case: String, number: String) -> String {
    if str_eq(number, "singular") {
        if str_eq(gram_case, "nominative") { return "τό" }
        if str_eq(gram_case, "genitive")   { return "τοῦ" }
        if str_eq(gram_case, "dative")     { return "τῷ" }
        if str_eq(gram_case, "accusative") { return "τό" }
        if str_eq(gram_case, "vocative")   { return "τό" }
        return "τό"
    }
    // plural
    if str_eq(gram_case, "nominative") { return "τά" }
    if str_eq(gram_case, "genitive")   { return "τῶν" }
    if str_eq(gram_case, "dative")     { return "τοῖς" }
    if str_eq(gram_case, "accusative") { return "τά" }
    if str_eq(gram_case, "vocative")   { return "τά" }
    return "τά"
}

fn grc_article(gender: String, gram_case: String, number: String) -> String {
    if str_eq(gender, "masculine") { return grc_article_masculine(gram_case, number) }
    if str_eq(gender, "feminine")  { return grc_article_feminine(gram_case, number) }
    // neuter
    return grc_article_neuter(gram_case, number)
}

// ── Infer gender from noun ending ─────────────────────────────────────────────
//
// Used by grc_noun_phrase when no explicit gender is provided.
// -ος -> masculine (default 2nd), -ον -> neuter, -α/-η -> feminine.

fn grc_infer_gender(noun: String) -> String {
    if grc_str_ends(noun, "ος") { return "masculine" }
    if grc_str_ends(noun, "ον") { return "neuter" }
    if grc_str_ends(noun, "α")  { return "feminine" }
    if grc_str_ends(noun, "η")  { return "feminine" }
    return "masculine"
}

// ── grc_noun_phrase: noun phrase builder ──────────────────────────────────────
//
// Produces a declined noun with optional definite article prepended.
// Gender is inferred from the noun ending when not supplied explicitly.
//
// noun:     nominative singular Greek noun
// gram_case: "nominative" | "accusative" | "genitive" | "dative" | "vocative"
// number:   "singular" | "plural"
// definite: "true" | "false"  (article is prepended when "true")

fn grc_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String {
    let declined: String = grc_decline(noun, gram_case, number)
    if str_eq(definite, "true") {
        let gender: String = grc_infer_gender(noun)
        let art: String = grc_article(gender, gram_case, number)
        return art + " " + declined
    }
    return declined
}
