import std/[strutils, unittest]

import ../src/embedded_bible
import ../src/kjv
import ../src/reference_parser

suite "reference parser":
  test "parses single verse references":
    let reference = parseReference("John 3:16")

    check reference.book.code == "JHN"
    check reference.ranges.len == 1
    check reference.ranges[0].start.chapter == 3
    check reference.ranges[0].start.verse == 16
    check reference.ranges[0].finish == reference.ranges[0].start
    check $reference == "John 3:16"

  test "parses verse lists using the previous chapter":
    let reference = parseReference("John 3:16,20-21")

    check reference.ranges.len == 2
    check reference.ranges[1].start.chapter == 3
    check reference.ranges[1].start.verse == 20
    check reference.ranges[1].finish.chapter == 3
    check reference.ranges[1].finish.verse == 21
    check $reference == "John 3:16, 3:20-21"

  test "parses chapter ranges":
    let reference = parseReference("John 3-4")

    check reference.ranges.len == 1
    check reference.ranges[0].start.chapter == 3
    check reference.ranges[0].start.verse == 0
    check reference.ranges[0].finish.chapter == 4
    check reference.ranges[0].finish.verse == 0
    check $reference == "John 3-4"

  test "parses abbreviated numbered books":
    let reference = parseReference("1 Jn 1:9")

    check reference.book.code == "1JN"
    check reference.ranges[0].start.chapter == 1
    check reference.ranges[0].start.verse == 9
    check $reference == "1 John 1:9"

  test "parses unique canonical book prefixes":
    check parseReference("Gene 1:1").book.code == "GEN"
    check parseReference("Phile 3").book.code == "PHM"
    check parseReference("Phili 1:6").book.code == "PHP"

  test "rejects ambiguous canonical book prefixes":
    expect ValueError:
      discard parseReference("Phil 1")

  test "normalizes single-chapter book references":
    let reference = parseReference("Jude 3-4")

    check reference.book.code == "JUD"
    check reference.ranges[0].start.chapter == 1
    check reference.ranges[0].start.verse == 3
    check reference.ranges[0].finish.chapter == 1
    check reference.ranges[0].finish.verse == 4
    check $reference == "Jude 3-4"

  test "parses semicolon-separated references":
    let references = parseReferences("Psalm 23; John 3:16")

    check references.len == 2
    check references[0].book.code == "PSA"
    check references[1].book.code == "JHN"

suite "offline KJV backend":
  test "fetches a single embedded verse":
    let passages = kjv.fetchPassages("John 3:16")

    check passages.len == 1
    check passages[0].startsWith("John 3:16\n")
    check passages[0].contains("  [16] ")

  test "fetches a single-chapter embedded verse":
    let passages = kjv.fetchPassages("Jude 3")

    check passages.len == 1
    check passages[0].startsWith("Jude 3\n")
    check passages[0].contains("  [3] ")

suite "embedded Bible layout":
  const layoutRows = """
JHN	8	31	0	paragraph	0	Then Jesus said,
JHN	8	31	1	same	0	"If you remain in My word,
JHN	8	32	0	same	0	you shall know the truth."
JHN	8	33	0	paragraph	0	They answered Him.
JHN	8	39	0	paragraph	0	They answered Him, "Abraham is our father."
JHN	8	39	1	paragraph	0	Jesus said to them, "If you were Abraham's children,
JHN	8	40	0	same	0	you would do the works of Abraham."
JHN	8	41	0	paragraph	0	You shall be free'
JHN	8	41	1	same	0	?
HEB	4	7	0	paragraph	0	again He establishes a certain day:
HEB	4	7	1	line	0	"Today, if you will hear His voice,
HEB	4	7	2	line	1	do not harden your hearts."
"""

  test "preserves inline verse markers within a paragraph":
    let passages = embedded_bible.fetchPassages(layoutRows, "John 8:31-32", "TEST")

    check passages.len == 1
    check passages[0] == "John 8:31-32\n" &
      "  [31] Then Jesus said, \"If you remain in My word, [32] you shall know the truth.\""

  test "preserves paragraph breaks":
    let passages = embedded_bible.fetchPassages(layoutRows, "John 8:31-33", "TEST")

    check passages[0] == "John 8:31-33\n" &
      "  [31] Then Jesus said, \"If you remain in My word, [32] you shall know the truth.\"\n" &
      "\n" &
      "  [33] They answered Him."

  test "preserves indented quote lines":
    let passages = embedded_bible.fetchPassages(layoutRows, "Hebrews 4:7", "TEST")

    check passages[0] == "Hebrews 4:7\n" &
      "  [7] again He establishes a certain day:\n" &
      "  \"Today, if you will hear His voice,\n" &
      "    do not harden your hearts.\""

  test "starts mid-paragraph ranges on a fresh line":
    let passages = embedded_bible.fetchPassages(layoutRows, "John 8:32-33", "TEST")

    check passages[0] == "John 8:32-33\n" &
      "  [32] you shall know the truth.\"\n" &
      "\n" &
      "  [33] They answered Him."

  test "joins markerless paragraph continuations":
    let passages = embedded_bible.fetchPassages(layoutRows, "John 8:39-40", "TEST")

    check passages[0] == "John 8:39-40\n" &
      "  [39] They answered Him, \"Abraham is our father.\" " &
      "Jesus said to them, \"If you were Abraham's children, " &
      "[40] you would do the works of Abraham.\""

  test "joins punctuation-only segments without extra spacing":
    let passages = embedded_bible.fetchPassages(layoutRows, "John 8:41", "TEST")

    check passages[0] == "John 8:41\n  [41] You shall be free'?"

  test "supports legacy verse rows":
    const legacyRows = "JHN\t3\t16\tFor God so loved the world.\n"
    let passages = embedded_bible.fetchPassages(legacyRows, "John 3:16", "TEST")

    check passages[0] == "John 3:16\n  [16] For God so loved the world."

  test "ignores layout metadata while rendering":
    const metadataRows =
      "JHN\t8\t31\t0\tparagraph\t0\tJesus said.\t" &
      """{"wordsOfChrist":true,"annotations":[{"kind":"crossReference","marker":"a","href":"index_split_1.html#x","offset":6}]}""" &
      "\n"
    let passages = embedded_bible.fetchPassages(metadataRows, "John 8:31", "TEST")

    check passages[0] == "John 8:31\n  [31] Jesus said."

  test "groups legacy rows into paragraphs using pilcrows":
    const legacyRows =
      "JHN\t8\t31\tThen Jesus said.\n" &
      "JHN\t8\t32\tYou shall know the truth.\n" &
      "JHN\t8\t33\t\xC2\xB6 They answered Him.\n"
    let passages = embedded_bible.fetchPassages(legacyRows, "John 8:31-33", "TEST")

    check passages[0] == "John 8:31-33\n" &
      "  [31] Then Jesus said. [32] You shall know the truth.\n" &
      "\n" &
      "  [33] They answered Him."

  test "plain output renders annotation footnotes":
    const rows =
      "JHN\t8\t1\t0\tparagraph\t0\tBut Jesus went to the Mount of Olives.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":40,"targetText":"Mt 21:1"}]}""" & "\n" &
      "JHN\t8\t2\t0\tsame\t0\tEarly in the morning He returned to the temple.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":49,"targetText":"Mt 26:55; Lk 4:20"}]}""" & "\n"
    let passages = embedded_bible.fetchPlainPassages(rows, "John 8:1-2", "TEST")

    check passages[0] == "1 But Jesus went to the Mount of Olives.[a] 2 Early in the morning He\n" &
      "returned to the temple.[b]\n" &
      "\n" &
      "a. Mt 21:1\n" &
      "b. Mt 26:55; Lk 4:20\n" &
      "\n" &
      "– John 8:1-2 (TEST)"

  test "plain output resets footnote labels per chapter":
    const rows =
      "JHN\t8\t59\t0\tparagraph\t0\tThey took up stones.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":21,"targetText":"Lev 24:16"}]}""" & "\n" &
      "JHN\t9\t1\t0\tparagraph\t0\tAs Jesus passed by.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":20,"targetText":"Jn 8:12"}]}""" & "\n"
    let passages = embedded_bible.fetchPlainPassages(rows, "John 8:59-9:1", "TEST")

    check passages[0] == "59 They took up stones.[a]\n" &
      "\n" &
      "a. Lev 24:16\n" &
      "\n" &
      "1 As Jesus passed by.[a]\n" &
      "\n" &
      "a. Jn 8:12\n" &
      "\n" &
      "– John 8:59-9:1 (TEST)"

  test "markdown output renders native footnotes":
    const rows =
      "JHN\t8\t1\t0\tparagraph\t0\tBut Jesus went to the Mount of Olives.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":40,"targetText":"Mt 21:1"}]}""" & "\n" &
      "JHN\t8\t2\t0\tsame\t0\tEarly in the morning He returned to the temple.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":49,"targetText":"Mt 26:55; Lk 4:20"}]}""" & "\n"
    let passages = embedded_bible.fetchMarkdownPassages(rows, "John 8:1-2", "TEST")

    check passages[0] == "> **1** But Jesus went to the Mount of Olives.[^a] **2** Early in the\n" &
      "> morning He returned to the temple.[^b]\n" &
      "\n" &
      "[^a]: Mt 21:1\n" &
      "[^b]: Mt 26:55; Lk 4:20\n" &
      "\n" &
      "> -- *John 8:1-2 (TEST)*"

  test "markdown output resets native footnotes per chapter":
    const rows =
      "JHN\t8\t59\t0\tparagraph\t0\tThey took up stones.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":21,"targetText":"Lev 24:16"}]}""" & "\n" &
      "JHN\t9\t1\t0\tparagraph\t0\tAs Jesus passed by.\t" &
      """{"annotations":[{"kind":"crossReference","marker":"a","offset":20,"targetText":"Jn 8:12"}]}""" & "\n"
    let passages = embedded_bible.fetchMarkdownPassages(rows, "John 8:59-9:1", "TEST")

    check passages[0] == "> **59** They took up stones.[^a]\n" &
      "\n" &
      "[^a]: Lev 24:16\n" &
      "\n" &
      "> **1** As Jesus passed by.[^a]\n" &
      "\n" &
      "[^a]: Jn 8:12\n" &
      "\n" &
      "> -- *John 8:59-9:1 (TEST)*"
