package solutions.tretter.githugandroid

/**
 * Port of the upstream ruby-githug `diff` 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 diffLevel(): Level = level(
    id = "diff",
    title = "Diff",
    description = "Since your last commit, file `app.rb` was modified. Find out which line has changed.",
    hints = listOf("You are looking for the difference since your last commit."),
    commandSuggestions = listOf("git diff"),
    setup = {
        RepoState(
            initialized = true,
            files = listOf(GitFile("app.rb", diffLevelModifiedAppRb(), tracked = true)),
            commits = listOf(CommitNode("0000001", "added app.rb")),
            branches = mapOf("master" to 1),
        )
    },
    nativeSetup = {
        resetFiles()
        write("app.rb", diffLevelBaselineAppRb())
        addCommit("added app.rb", "app.rb")
        write("app.rb", diffLevelModifiedAppRb())
        true
    },
    validator = commandAnswer("26"),
    testCases = listOf(
        levelTestCase("answer changed line", "26"),
    ),
    setupChecks = listOf(
        levelSetupCheck(
            "upstream changed line is present",
            "diff should start with app.rb modified to use server.json on the changed line.",
        ) { repo ->
            repo.files.firstOrNull { it.name == "app.rb" }?.content?.contains("@message = get_response('server.json')") == true
        },
    ),
)

internal fun diffLevelBaselineAppRb(): String =
    """
    require 'sinatra'
    require 'oauth2'
    require 'json'
    enable :sessions

    def client
      OAuth2::Client.new("mTeZFqkCmzc8JnjKXaSww95bFFxhUpp1wwmSi8vG", "a9OMyEdW7JvWThHmmvFcShR9P2dyad3EGuA2ULDh", :site => "http://localhost:3000")
    end

    get "/auth/test" do
      redirect client.auth_code.authorize_url(:redirect_uri => redirect_uri)
    end

    get '/auth/test/callback' do
      access_token = client.auth_code.get_token(params[:code], :redirect_uri => redirect_uri)
      session[:access_token] = access_token.token
      @message = "Successfully authenticated with the server"
      erb :success
    end

    get '/yet_another' do
      @message = get_response('data.json')
      erb :success
    end
    get '/another_page' do
      @message = get_response('data.json')
      erb :another
    end

    def get_response(url)
      access_token = OAuth2::AccessToken.new(client, session[:access_token])
      JSON.parse(access_token.get("/api/v1/#{url}").body)
    end


    def redirect_uri
      uri = URI.parse(request.url)
      uri.path = '/auth/test/callback'
      uri.query = nil
      uri.to_s
    end
    """.trimIndent() + "\n"

internal fun diffLevelModifiedAppRb(): String =
    diffLevelBaselineAppRb().replace(
        "get '/another_page' do\n  @message = get_response('data.json')",
        "get '/another_page' do\n  @message = get_response('server.json')",
    )
