EngineRest <- R6::R6Class("EngineRest",
  inherit = Engine,
  public = list(
    rest_api_url = NULL,
    initialize = function(rest_api_url = NA,
                          token = NA,
                          scan_all = FALSE) {
      private$engine <- "rest"
      private$token <- token
      self$rest_api_url <- rest_api_url
      private$scan_all <- scan_all
      private$set_endpoints()
    },

    response = function(endpoint,
                        token = private$token,
                        verbose) {
      response <- self$perform_request(
        endpoint = endpoint,
        token = token,
        verbose = verbose
      )
      result <- response |>
        httr2::resp_body_json(check_type = FALSE) |>
        private$set_rest_error_class()
      return(result)
    },

    perform_request = function(endpoint, token, verbose) {
      resp <- httr2::request(endpoint) |>
        httr2::req_headers("Authorization" = paste0("Bearer ", token)) |>
        httr2::req_error(is_error = function(resp) FALSE) |>
        httr2::req_perform()
      if (resp$status_code == 401 && verbose) {
        cli::cli_alert_danger("HTTP 401 Unauthorized.")
      }
      if (resp$status_code == 404 && verbose) {
        cli::cli_alert_danger("HTTP 404 Not Found.")
      }
      if (resp$status_code %in% c(400, 500, 403)) {
        resp <- httr2::request(endpoint) |>
          httr2::req_headers("Authorization" = paste0("Bearer ", token)) |>
          httr2::req_retry(
            is_transient = ~ httr2::resp_status(.x) %in% c(400, 500, 403),
            max_seconds = 60
          ) |>
          httr2::req_perform()
      }
      return(resp)
    }

  ),
  private = list(
    set_rest_error_class = function(resp) {
      if (!is.null(resp$message) && grepl("404", resp$message)) {
        class(resp) <- c("rest_error", "404_not_found", class(resp))
      }
      resp
    },

    get_contributors_from_repo = function(contributors_endpoint, user_name, verbose) {
      contributors_response <- private$paginate_results(
        endpoint = contributors_endpoint,
        verbose = verbose
      )
      contributors_vec <- contributors_response |>
        purrr::map_chr(~ eval(user_name)) |>
        paste0(collapse = ", ")
      return(contributors_vec)
    },

    paginate_results = function(endpoint, joining_sign = "?", verbose = TRUE) {
      full_response <- list()
      page <- 1
      repeat {
        endpoint_with_pagination <- paste0(endpoint, joining_sign, "per_page=100&page=", page)
        response_page <- self$response(
          endpoint = endpoint_with_pagination,
          verbose = verbose
        )
        if (inherits(response_page, "rest_error")) {
          response_page <- NULL
        }
        if (length(response_page) > 0) {
          full_response <- append(full_response, response_page)
          page <- page + 1
        } else {
          break
        }
      }
      return(full_response)
    }
  )
)
