# frozen_string_literal: true

# Security::VulnerabilityFindingsFinder
#
# Used to filter Vulnerabilities::Occurrences  by set of params for Security Dashboard
#
# Arguments:
#   vulnerable - object to filter vulnerabilities
#   params:
#     severity: Array<String>
#     confidence: Array<String>
#     project: Array<String>
#     report_type: Array<String>
#     scope: String

module Security
  class VulnerabilityFindingsFinder
    attr_accessor :params
    attr_reader :vulnerable

    def initialize(vulnerable, params: {})
      @vulnerable = vulnerable
      @params = params
    end

    def execute(collection_scope = :latest)
      collection = init_collection(collection_scope)
      collection = by_report_type(collection)
      collection = by_project(collection)
      collection = by_severity(collection)
      collection = by_confidence(collection)
      collection = by_scope(collection)
      collection
    end

    private

    def by_report_type(items)
      return items unless params[:report_type].present?

      items.by_report_types(
        Vulnerabilities::Occurrence::REPORT_TYPES.values_at(
          *params[:report_type]).compact)
    end

    def by_project(items)
      return items unless params[:project_id].present?

      items.by_projects(params[:project_id])
    end

    def by_severity(items)
      return items unless params[:severity].present?

      items.by_severities(
        Vulnerabilities::Occurrence::SEVERITY_LEVELS.values_at(
          *params[:severity]).compact)
    end

    def by_confidence(items)
      return items unless params[:confidence].present?

      items.by_confidences(
        Vulnerabilities::Occurrence::CONFIDENCE_LEVELS.values_at(
          *params[:confidence]).compact)
    end

    def by_scope(items)
      # We're using the same params as the public Vulnerabilities API because the frontend uses both
      # https://gitlab.com/gitlab-org/gitlab/issues/33468 fixes issue with param name meaning
      return items if params[:scope] == 'all'

      items.undismissed
    end

    def init_collection(collection_scope)
      case collection_scope
      when :all
        vulnerable.all_vulnerabilities
      when :with_sha
        vulnerable.latest_vulnerabilities_with_sha
      when :latest
        vulnerable.latest_vulnerabilities
      else
        raise ArgumentError, "invalid value for 'collection_scope': #{collection_scope}"
      end
    end
  end
end
