package solutions.tretter.githugandroid

/**
 * Port of the upstream ruby-githug `conflict` level.
 *
 * Setup documents the repository shape the learner explores. Evaluation is kept
 * state-based whenever the exercise changes repository objects; answer-only
 * levels intentionally validate the answer entered at the prompt.
 */
internal fun conflictLevel(): Level = level(
    id = "conflict",
    title = "Conflict",
    description = "You need to merge mybranch into the current branch (master). But there may be some incorrect changes in mybranch which may cause conflicts. Solve any merge-conflicts you come across and finish the merge.",
    hints = emptyList(),
    commandSuggestions = listOf("git merge mybranch"),
    setup = {
        RepoState(
            initialized = true,
            files = listOf(GitFile("poem.txt", conflictLevelMasterPoem(), tracked = true)),
            branches = mapOf("master" to 3, "mybranch" to 4),
        )
    },
    nativeSetup = {
        resetFiles()
        write("poem.txt", conflictLevelInitialPoem())
        addCommit("Initial commit", "poem.txt")
        checkoutNew("mybranch")
        write("poem.txt", conflictLevelBranchWrongPoem())
        addCommit("Added lines", "poem.txt")
        append("poem.txt", "\nThis is a cool poem everyone should learn.\n")
        addCommit("Added comment", "poem.txt")
        write("poem.txt", conflictLevelSolvedPoem())
        addCommit("Changed the poem", "poem.txt")
        checkout("master")
        write("poem.txt", conflictLevelSolvedPoem())
        addCommit("Added two lines", "poem.txt")
        write("poem.txt", conflictLevelMasterPoem())
        addCommit("Updated the poem", "poem.txt")
        true
    },
    validator = repoPredicate { repo ->
        val poem = repo.files.find { it.name == "poem.txt" }?.content.orEmpty()
        repo.headBranch == "master" &&
            repo.commits.firstOrNull()?.parentCount == 2 &&
            "Sat on a wall" in poem &&
            poem.none { it in "<>=|" }
    },
    testCases = listOf(
        levelTestCase(
            "merge and resolve cleanly",
            "git merge mybranch",
            "echo \"Humpty dumpty\" > poem.txt",
            "echo \"Sat on a wall\" >> poem.txt",
            "echo \"Humpty dumpty\" >> poem.txt",
            "echo \"Had a great fall\" >> poem.txt",
            "git add poem.txt",
            "git commit --no-edit",
        ),
    ),
    negativeTestCases = listOf(
        levelTestCase(
            "editing conflict text and rerunning merge does not solve",
            "git merge mybranch",
            "echo \"Humpty dumpty\" > poem.txt",
            "echo \"Sat on a wall\" >> poem.txt",
            "echo \"Humpty dumpty\" >> poem.txt",
            "echo \"Had a great fall\" >> poem.txt",
            "git merge mybranch",
        ),
    ),
    setupChecks = listOf(
        levelSetupCheck(
            "upstream poem starts on master",
            "conflict should start on master with upstream poem text and mybranch present.",
        ) { repo ->
            repo.headBranch == "master" &&
                repo.fileContent("poem.txt").contains("Categorized shoes by color") &&
                repo.branches.containsKey("mybranch")
        },
    ),
)

private fun conflictLevelInitialPoem(): String =
    """
    Humpty dumpty
    Had a great fall
    """.trimIndent() + "\n"

private fun conflictLevelBranchWrongPoem(): String =
    """
    Humpty dumpty
    Fell on a doll
    Humpty dumpty
    Had a great fall
    """.trimIndent() + "\n"

private fun conflictLevelSolvedPoem(): String =
    """
    Humpty dumpty
    Sat on a wall
    Humpty dumpty
    Had a great fall
    """.trimIndent() + "\n"

private fun conflictLevelMasterPoem(): String =
    """
    Humpty dumpty
    Categorized shoes by color
    Humpty dumpty
    Had a great fall
    """.trimIndent() + "\n"

private fun RepoState.fileContent(path: String): String = files.firstOrNull { it.name == path }?.content.orEmpty()
