#!/usr/bin/env ruby

$LOAD_PATH.unshift File.expand_path('../lib', __dir__)

require 'test_info'
require 'gpt_common'
require 'optimist'
require 'run_k6'
require 'table_print'

# Get parent folder(`k6`) path from the current file
k6_dir = File.expand_path('../k6', __dir__)
tp.set(:max_width, 800)

@opts = Optimist.options do
  banner "Usage: ci-report-test-info-wiki [options]"
  banner "\nReports GitLab Performance Tool test details to a Wiki. Designed for us in GitLab CI."
  banner "\nOptions:"
  opt :help, 'Show help message'
  opt :page_title, "Title to use for wiki page", type: :string, required: true
  opt :environment, "Name of Environment Config file in environments directory that the test(s) will be run with. Alternative filepath can also be given.", type: :string, default: 'staging.json'
  opt :api_url, "GitLab Wiki API URL, e.g. https://gitlab.com/api/v4/projects/<ID or encoded path>/wikis", type: :string, required: true
  opt :dry_run, "Only generate Wiki page locally and don't post for testing purposes.", type: :flag
  banner "\nEnvironment Variable(s):"
  banner "  CI_PROJECT_ACCESS_TOKEN   A valid GitLab Personal Access Token that has access to the intended project where the wiki page will be posted. The token should come from a User that has admin access for the project(s) and have all permissions. (Default: nil)"
end

raise 'Environment Variable CI_PROJECT_ACCESS_TOKEN must be set to proceed. See command help for more info' unless ENV['CI_PROJECT_ACCESS_TOKEN'] || @opts[:dry_run]

env_file = Dir.glob([@opts[:environment], "#{ENV['GPT_DOCKER_CONFIG_DIR'] || ''}/environments/#{@opts[:environment]}", "#{k6_dir}/#{@opts[:environment]}", "#{k6_dir}/config/environments/#{@opts[:environment]}"])[0]
raise "Environment config file '#{opts[:environment]}' not found as given or in default folder. Exiting..." unless File.file?(env_file.to_s)

puts "Collecting test info..."
opts = { tests: ["tests"], quarantined: true, experimental: true, scenarios: true, unsafe: true, vulnerabilities: true, rate_limits: false, unattended: true, test_excludes: [] }
tests = RunK6.get_tests(k6_dir:, opts:)
env_file_vars = RunK6.setup_env_file_vars(k6_dir:, env_file:)
tests_info = TestInfo.get_tests_info(tests)
test_type_order = %w[api git scenarios web] # quarantine and experimental should be after main test types
test_types = tests_info.map { |test_info| test_info[:type] }.uniq.sort_by { |type| test_type_order.include?(type) ? 0 : 1 }
tests_with_issues = tests_info.select { |test_info| !test_info[:issues].nil? }
tests_with_previous_issues = tests_info.select { |test_info| !test_info[:previous_issues].nil? }

tests_info = TestInfo.get_test_urls(tests_info, env_file_vars)

wiki_report_contents = <<~DOC
  GitLab Performance Tool provides several different types of tests:
  * [`api`](#api) - API endpoint tests
  * [`git`](#git) - git-related tests
  * [`scenarios`](#scenarios) - standalone test scenarios
  * [`web`](#web) - Web page tests
  * [`quarantined`](#quarantined) - tests that are quarantined because of some ongoing issue with endpoint or test itself
  * [`experimental`](#experimental) - tests that are related to features that are experimental or not GA

  **Note:** Some endpoints have [known issues](#known-issues). These tests have either been run with a custom lower threshold limit applied or are quarantined until the issue is fixed.
  Historical performance issues for specific endpoints are listed in [closed performance issues](#closed-performance-issues) section.

  The 'Stressed Components' column highlights GitLab components under pressure during testing.
  While it offers insights into failure patterns, it's not exhaustive.
  Investigation on a case-by-case basis, considering resource utilization and GitLab logs, is essential for a comprehensive understanding.
DOC

test_types.each do |type|
  wiki_report_contents << "\n## #{type.include?('api') ? type.upcase : type.capitalize}\n"
  tests_info_by_type = tests_info.select { |test| test[:type] == type }
  wiki_report_contents << TablePrint::Printer.table_print(tests_info_by_type, [{ link_md: { display_name: :tests } }, :description, :stressed_components, { endpoints: ->(endpoint) { "#{endpoint[:endpoint]}<br><br>#{endpoint[:url]}" } }])
end

wiki_report_contents << "\n## Known Issues\n"
wiki_report_contents << TablePrint::Printer.table_print(tests_with_issues, [:name, :issues])

wiki_report_contents << "\n## Closed Performance Issues\n"
wiki_report_contents << TablePrint::Printer.table_print(tests_with_previous_issues, [:name, :previous_issues])

exit if @opts[:dry_run]

puts "Posting test info to Wiki page..."
headers = { 'PRIVATE-TOKEN': ENV['CI_PROJECT_ACCESS_TOKEN'] }

create_params = {
  title: @opts[:page_title],
  content: "Autogenerated by GitLab Performance Tool"
}
GPTCommon.make_http_request(method: 'post', url: @opts[:api_url], params: create_params, headers:, fail_on_error: false)

edit_params = {
  title: @opts[:page_title],
  content: wiki_report_contents
}
GPTCommon.make_http_request(method: 'put', url: "#{@opts[:api_url]}/#{@opts[:page_title]}", params: edit_params, headers:)
puts "Test info posted"
