# frozen_string_literal: true

require 'http'
require 'json'

module GitlabQuality
  module TestTooling
    module Report
      class TestHealthIssueFinder < ReportAsIssue
        HEALTH_PROBLEM_TYPE_TO_LABEL = {
          'pass-after-retry' => 'test-health:pass-after-retry',
          'slow' => 'test-health:slow',
          'failures' => 'test-health:failures'
        }.freeze

        def initialize(health_problem_type: [], **kwargs)
          super(**kwargs)

          @health_problem_type = health_problem_type
        end

        def found_existing_unhealthy_test_issue?
          issue_url = invoke!

          !issue_url.nil? && !issue_url.empty?
        end

        def run!
          existing_issue_found = nil

          applicable_tests.each do |test|
            issues = find_issues_by_hash(test_hash(test), state: 'opened', labels: search_labels)
            next if issues.empty?

            existing_issue_found = issues.first.web_url
            puts "Found an existing test health issue of type #{health_problem_type} for test #{test.file}:#{test.line_number}: #{existing_issue_found}."
            break
          end

          puts "Did not find an existing test health issue of type #{health_problem_type}." unless existing_issue_found

          existing_issue_found
        end

        def applicable_tests
          applicable_tests = []

          TestResults::Builder.new(file_glob: files, token: token, project: project).test_results_per_file do |test_results|
            applicable_tests = test_results.select { |test| test_is_applicable?(test) }
          end

          applicable_tests
        end

        private

        attr_reader :health_problem_type

        # Be mindful about the number of tests this method would return,
        # as we will make at least one API request per test.
        def test_is_applicable?(test)
          expected_test_status =
            case health_problem_type
            when 'failures'
              'failed'
            else
              'passed'
            end

          test.status == expected_test_status
        end

        def search_labels
          ['test', HEALTH_PROBLEM_TYPE_TO_LABEL[health_problem_type]]
        end
      end
    end
  end
end