# typed: false
# frozen_string_literal: true

module API
  module TestHelpers
    include Rack::Test::Methods

    def plug(method, path, headers: {}, version: nil, body: {})
      version ||= PlugApp::CURRENT_VERSION
      prepended_path = prepend_plug_path(version, path)

      http_call(method, prepended_path, headers: headers, version: version, body: body)
    end

    def api(method, path, headers: {}, version: nil, body: {})
      version ||= PlugApp::CURRENT_VERSION
      prepended_path = prepend_api_path(version, path)

      http_call(method, prepended_path, headers: headers, version: version, body: body)
    end

    def http_call(method, path, headers: {}, version: nil, body: {})
      # explicitly assert headers cannot be nil
      if headers.nil?
        send(method, path, body.to_json)
      else
        headers["HTTP_ACCEPT"] ||= headers.fetch("HTTP_ACCEPT", "application/json")
        headers["CONTENT_TYPE"] ||= headers.fetch("CONTENT_TYPE", "application/json")
        send(method, path, body.to_json, headers)
      end

      JSON.parse(last_response.body) if last_response.body.present?
    end

    def assert_response(expected_status, expected_body = nil)
      expected_status = case expected_status
      when :not_found
        PlugApp::HTTP::NOT_FOUND_I
      when :not_acceptable
        PlugApp::HTTP::NOT_ACCEPTABLE_I
      when :ok, :okay
        PlugApp::HTTP::OK_I
      when :created
        PlugApp::HTTP::CREATED_I
      when :no_content
        PlugApp::HTTP::NO_CONTENT_I
      when :bad_request
        PlugApp::HTTP::BAD_REQUEST_I
      when :unauthorized
        PlugApp::HTTP::UNAUTHORIZED_I
      when :forbidden
        PlugApp::HTTP::FORBIDDEN_I
      when :service_unavailable
        PlugApp::HTTP::SERVICE_UNAVAILABLE_I
      else
        raise ArgumentError, "Unknown status: #{expected_status}"
      end

      assert_equal(expected_status, last_response.status)
    end

    def prepend_plug_path(version, path)
      "/app/#{version}#{path}"
    end

    def prepend_api_path(version, path)
      "/api/#{version}#{path}"
    end

    def app
      Rails.application
    end
  end
end