package solutions.tretter.githugandroid

/**
 * Port of the upstream ruby-githug `cherry-pick` 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 cherryPickLevel(): Level = level(
    id = "cherry-pick",
    title = "Cherry Pick",
    description = "Your new feature isn't worth the time and you're going to delete it. But it has one commit that fills in `README` file, and you want this commit to be on the master as well.",
    hints = listOf("Sneak a peek at the `git help cherry-pick` command."),
    commandSuggestions = listOf("git log --oneline new-feature", "git cherry-pick <commit>"),
    setup = {
        RepoState(
            initialized = true,
            files = listOf(
                GitFile("README.md", "I'll fill in the file some time later..\n", tracked = true),
                GitFile("hardcore-math.js", cherryPickLevelHardcoreMathJs(), tracked = true),
                GitFile("nokia.js", "console.log(\"[NOKIA] Connecting people\");\n", tracked = true),
            ),
            commits = listOf(
                CommitNode("0000001", "Added fancy branded output"),
                CommitNode("0000002", "Renamed project.js -> herdcore-math.js"),
                CommitNode("0000003", "Added a hardcore math module"),
                CommitNode("0000004", "Initial commit"),
            ),
            branches = mapOf("master" to 4, "new-feature" to 5),
        )
    },
    validator = repoPredicate { repo ->
        repo.files.any { it.name == "README.md" && it.tracked } &&
            repo.headBranch == "master" &&
            repo.commits.take(2).map { it.message } == listOf("Filled in README.md with proper input", "Added fancy branded output")
    },
    nativeSetup = {
        resetFiles()
        write("README.md", "I'll fill in the file some time later..\n")
        addCommit("Initial commit", "README.md")
        write("project.js", "for(var i = 0; i < 10; i++) {\n    console.log(42 * i);\n}\n")
        addCommit("Added a hardcore math module", "project.js")
        git("mv", "project.js", "hardcore-math.js")
        commit("Renamed project.js -> herdcore-math.js")
        write("nokia.js", "console.log(\"[NOKIA] Connecting people\");\n")
        addCommit("Added fancy branded output", "nokia.js")
        git("branch", "new-feature", "HEAD~3")
        checkout("new-feature")
        write("feature.js", "function connect() {\n}\n")
        addCommit("Added a stub for the feature", "feature.js")
        write("README.md", "This project now documents its proper input.\n")
        addCommit("Filled in README.md with proper input", "README.md")
        append("feature.js", "connect();\n")
        addCommit("Fixed feature", "feature.js")
        append("feature.js", "console.log('done');\n")
        addCommit("some small fixes", "feature.js")
        checkout("master")
        true
    },
    testCases = listOf(
        levelTestCase("cherry pick README commit", "git cherry-pick new-feature~2"),
    ),
    setupChecks = listOf(
        levelSetupCheck(
            "upstream cherry-pick files and branch are present",
            "cherry-pick should start with upstream README.md, hardcore-math.js, and new-feature branch.",
        ) { repo ->
            repo.files.firstOrNull { it.name == "README.md" }?.content?.contains("I'll fill in the file some time later..") == true &&
                repo.files.firstOrNull { it.name == "hardcore-math.js" }?.content?.contains("console.log(42 * i);") == true &&
                repo.branches.containsKey("new-feature")
        },
    ),
)

private fun cherryPickLevelHardcoreMathJs(): String =
    """
    for(var i = 0; i < 10; i++) {
        console.log(42 * i);
    }
    """.trimIndent() + "\n"
