package solutions.tretter.githugandroid

/**
 * Port of the upstream ruby-githug `grep` 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 grepLevel(): Level = level(
    id = "grep",
    title = "Grep",
    description = "Your project's deadline approaches, you should evaluate how many TODOs are left in your code",
    hints = listOf("You want to research the `git grep` command."),
    commandSuggestions = listOf("git grep TODO"),
    setup = {
        RepoState(
            initialized = true,
            files = listOf(
                GitFile("app.rb", grepLevelAppRb(), tracked = true),
                GitFile("config.rb", grepLevelConfigRb(), tracked = true),
            ),
            commits = listOf(CommitNode("0000001", "Add application files.")),
            branches = mapOf("master" to 1),
        )
    },
    nativeSetup = {
        resetFiles()
        write("app.rb", grepLevelAppRb())
        write("config.rb", grepLevelConfigRb())
        addCommit("Add application files.", "app.rb", "config.rb")
        true
    },
    validator = commandAnswer("4"),
    testCases = listOf(
        levelTestCase("answer todo count", "4"),
    ),
    setupChecks = listOf(
        levelSetupCheck(
            "upstream TODO files are present",
            "grep should start with upstream app.rb and config.rb TODO entries.",
        ) { repo ->
            repo.files.firstOrNull { it.name == "app.rb" }?.content?.contains("# TODO Make site url variable.") == true &&
                repo.files.firstOrNull { it.name == "config.rb" }?.content?.contains("# TODO Move password to a configuration file.") == true
        },
    ),
)

private fun grepLevelAppRb(): String =
    """
    require 'sinatra'
    require 'oauth2'
    require 'json'
    enable :sessions

    # TODO Make site url variable.
    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('server.json')
      erb :another
    end

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

    # TODO Redirecting queries could be useful.
    def redirect_uri
      uri = URI.parse(request.url)
      uri.path = '/auth/test/callback'
      uri.query = nil
      uri.to_s
    end
    """.trimIndent() + "\n"

private fun grepLevelConfigRb(): String =
    """
    class Config
      attr_accessor :name, :password
      def initialize(name, password = nil, options = {})
        @name = name
        # TODO Move password to a configuration file.
        @password = password || "i<3evil"

        if options[:downcase]
          @name.downcase!
        end

        if options[:upcase]
          @name.upcase!
        end

      end
    end
    """.trimIndent() + "\n"
