class Gitlab::QA::Report::ReportAsIssue

def assert_input_files!(files)

def assert_input_files!(files)
  return if Dir.glob(files).any?
  abort "Please provide valid JUnit report files. No files were found matching `#{files.join(',')}`"
end

def assert_project!

def assert_project!
  return if project
  abort "Please provide a valid project ID or path with the `-p/--project` option!"
end

def create_issue(test)

def create_issue(test)
  gitlab.create_issue(
    title: title_from_test(test),
    description: new_issue_description(test),
    labels: new_issue_labels(test).to_a
  )
end

def ee_test?(test)

def ee_test?(test)
  test.file =~ %r{features/ee/(api|browser_ui)}
end

def initialize(token:, input_files:, project: nil, dry_run: false, **kwargs)

def initialize(token:, input_files:, project: nil, dry_run: false, **kwargs)
  @project = project
  @gitlab = (dry_run ? GitlabIssueDryClient : GitlabIssueClient).new(token: token, project: project)
  @files = Array(input_files)
end

def invoke!

def invoke!
  validate_input!
  run!
end

def issue_labels(issue)

def issue_labels(issue)
  issue&.labels&.to_set || Set.new
end

def new_issue_description(test)

def new_issue_description(test)
  "### Full description\n\n#{search_safe(test.name)}\n\n### File path\n\n#{test.file}"
end

def new_issue_labels(test)

def new_issue_labels(test)
  []
end

def new_issue_title(test)

def new_issue_title(test)
  "#{partial_file_path(test.file)} | #{search_safe(test.name)}".strip
end

def partial_file_path(path)

def partial_file_path(path)
  path.match(/((api|browser_ui).*)/i)[1]
end

def pipeline

def pipeline
  # Gets the name of the pipeline the test was run in, to be used as the key of a scoped label
  #
  # Tests can be run in several pipelines:
  #   gitlab-qa, nightly, staging, canary, production, preprod, MRs, and the default branch (master/main)
  #
  # Some of those run in their own project, so CI_PROJECT_NAME is the name we need. Those are:
  #   nightly, staging, canary, production, and preprod
  #
  # MR, master/main, and gitlab-qa tests run in gitlab-qa, but we only want to report tests run on
  # master/main because the other pipelines will be monitored by the author of the MR that triggered them.
  # So we assume that we're reporting a master/main pipeline if the project name is 'gitlab-qa'.
  @pipeline ||= Runtime::Env.pipeline_from_project_name
end

def pipeline_name_label

def pipeline_name_label
  case pipeline
  when 'production'
    'found:gitlab.com'
  when 'canary', 'staging'
    "found:#{pipeline}.gitlab.com"
  when 'preprod'
    'found:pre.gitlab.com'
  when 'staging-orchestrated', 'nightly', QA::Runtime::Env.default_branch
    "found:#{pipeline}"
  else
    raise "No `found:*` label for the `#{pipeline}` pipeline!"
  end
end

def quarantine_job?

def quarantine_job?
  Runtime::Env.ci_job_name&.include?('quarantine')
end

def run!

def run!
  raise NotImplementedError
end

def search_safe(value)

def search_safe(value)
  value.delete('"')
end

def test_results_per_file

def test_results_per_file
  Dir.glob(files).each do |path|
    extension = File.extname(path)
    test_results =
      case extension
      when '.json'
        Report::JsonTestResults.new(path)
      when '.xml'
        Report::JUnitTestResults.new(path)
      else
        raise "Unknown extension #{extension}"
      end
    yield test_results
  end
end

def title_from_test(test)

def title_from_test(test)
  title = new_issue_title(test)
  return title unless title.length > MAX_TITLE_LENGTH
  "#{title[0...MAX_TITLE_LENGTH - 3]}..."
end

def up_to_date_labels(test:, issue: nil)

def up_to_date_labels(test:, issue: nil)
  labels = issue_labels(issue)
  labels << "Enterprise Edition" if ee_test?(test)
  quarantine_job? ? labels << "quarantine" : labels.delete("quarantine")
  labels
end

def update_labels(issue, test)

def update_labels(issue, test)
  new_labels = up_to_date_labels(test: test, issue: issue)
  return if issue_labels(issue) == new_labels
  gitlab.edit_issue(iid: issue.iid, options: { labels: new_labels.to_a })
end

def validate_input!

def validate_input!
  assert_project!
  assert_input_files!(files)
  gitlab.assert_user_permission!
end