package solutions.tretter.githugandroid

/**
 * Android-native adaptation of the upstream ruby-githug `bisect` level.
 *
 * Upstream ships a Ruby fixture where `ruby prog.rb 5` should output 15.
 * Android does not bundle Ruby, so this level keeps the same lesson and answer
 * style but uses a POSIX shell test script committed into the exercise repo.
 */
internal fun bisectLevel(): Level = level(
    id = "bisect",
    title = "Bisect",
    description = "A balance check started failing somewhere in the history. The current HEAD is bad: `./test-balance.sh` prints `balance broken`. Use `git bisect` to locate the break, then enter the abbreviated hash of the last good commit.",
    hints = listOf(
        "Mark the current HEAD as bad, because the test fails there.",
        "`known-good` marks a commit where the balance check passes.",
        "`git bisect run ./test-balance.sh` identifies the first bad commit; the last good commit is its parent in this linear history.",
    ),
    commandSuggestions = listOf(
        "./test-balance.sh",
        "git bisect start",
        "git bisect bad HEAD",
        "git bisect good known-good",
        "git bisect run ./test-balance.sh",
    ),
    setup = {
        RepoState(
            initialized = true,
            branches = mapOf("master" to 7),
            tags = listOf("known-good"),
            commits = listOf(
                CommitNode("7", "Polish report labels"),
                CommitNode("6", "Add forecast note"),
                CommitNode("5", "Update help text"),
                CommitNode("4", "Break closing balance calculation"),
                CommitNode("3", "Add audit note"),
                CommitNode("2", "Add January note"),
                CommitNode("1", "Add balance check"),
            ),
        )
    },
    nativeSetup = {
        resetFiles()
        write("balance.txt", "BALANCE=100\n")
        write(
            "test-balance.sh",
            """
            |#!/bin/sh
            |while IFS= read -r line
            |do
            |  if test "${'$'}line" = "BALANCE=100"
            |  then
            |    echo "balance ok"
            |    exit 0
            |  fi
            |done < balance.txt
            |echo "balance broken"
            |exit 1
            |""".trimMargin(),
        )
        addCommit("Add balance check", "balance.txt", "test-balance.sh")
        tag("known-good")
        write("notes.txt", "January review complete\n")
        addCommit("Add January note", "notes.txt")
        append("notes.txt", "Audit trail reviewed\n")
        addCommit("Add audit note", "notes.txt")
        write("balance.txt", "BALANCE=101\n")
        addCommit("Break closing balance calculation", "balance.txt")
        write("README", "Run ./test-balance.sh to check the report.\n")
        addCommit("Update help text", "README")
        append("notes.txt", "Forecast still depends on the balance check\n")
        addCommit("Add forecast note", "notes.txt")
        append("README", "Use git bisect to find the last good commit before the report broke.\n")
        addCommit("Polish report labels", "README")
        true
    },
    validator = { repo, command ->
        val lastGoodCommit = repo.commits.firstOrNull { it.message == "Add audit note" }
        val normalized = command.trim()
        lastGoodCommit != null &&
            normalized.length >= 4 &&
            !normalized.startsWith("git ") &&
            (normalized.startsWith(lastGoodCommit.id, ignoreCase = true) || lastGoodCommit.id.startsWith(normalized, ignoreCase = true))
    },
    testCases = listOf(
        levelTestCase(
            "answer last good commit",
            "git bisect start",
            "git bisect bad HEAD",
            "git bisect good known-good",
            "git bisect run ./test-balance.sh",
            "c8c7c00",
        ),
    ),
    negativeTestCases = listOf(
        levelTestCase(
            "bisect run alone does not solve",
            "git bisect start",
            "git bisect bad HEAD",
            "git bisect good known-good",
            "git bisect run ./test-balance.sh",
        ),
    ),
)
