# frozen_string_literal: true

module API
  class VulnerabilityFindings < Grape::API
    include PaginationParams
    include ::Gitlab::Utils::StrongMemoize

    helpers do
      def pipeline
        strong_memoize(:pipeline) do
          if params[:pipeline_id]
            user_project.all_pipelines.for_id(params[:pipeline_id]).first
          else
            user_project.latest_pipeline_with_security_reports
          end
        end
      end

      def vulnerability_occurrences_by(params)
        return [] unless pipeline

        aggregated_report = Security::PipelineVulnerabilitiesFinder.new(pipeline: pipeline, params: params).execute
        aggregated_report.occurrences
      end
    end

    before do
      authenticate!
    end

    params do
      requires :id, type: String, desc: 'The ID of a project'
    end
    resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
      params do
        optional :report_type, type: Array[String], desc: 'The type of report vulnerability belongs to',
                 values: ::Vulnerabilities::Occurrence.report_types.keys,
                 default: ::Vulnerabilities::Occurrence.report_types.keys
        optional :scope, type: String, desc: 'Return vulnerabilities for the given scope: `dismissed` or `all`',
                 default: 'dismissed', values: %w[all dismissed]
        optional :severity,
                 type: Array[String],
                 desc: 'Returns vulnerabilities belonging to specified severity level: '\
                       '`info`, `unknown`, `low`, `medium`, `high`, or `critical`. Defaults to all',
                 values: ::Vulnerabilities::Occurrence.severities.keys,
                 default: ::Vulnerabilities::Occurrence.severities.keys
        optional :confidence,
                 type: Array[String],
                 desc: 'Returns vulnerabilities belonging to specified confidence level: '\
                       '`undefined`, `ignore`, `unknown`, `experimental`, `low`, `medium`, `high`, or `confirmed`. '\
                       'Defaults to all',
                 values: ::Vulnerabilities::Occurrence.confidences.keys,
                 default: ::Vulnerabilities::Occurrence.confidences.keys
        optional :pipeline_id, type: String, desc: 'The ID of the pipeline'

        use :pagination
      end
      desc 'Get a list of project vulnerability findings' do
        success ::Vulnerabilities::OccurrenceEntity
      end
      get ':id/vulnerability_findings' do
        authorize! :read_vulnerability, user_project

        # We might have to add rubocop:disable annotation here in case
        # https://gitlab.com/gitlab-org/gitlab/issues/32763 happens, using
        # Kaminari.paginate_array here is correct
        # See https://gitlab.com/gitlab-org/gitlab/issues/33588#note_291849433
        # for discussion
        vulnerability_occurrences = paginate(
          Kaminari.paginate_array(
            vulnerability_occurrences_by(declared_params)
          )
        )

        Gitlab::Vulnerabilities::OccurrencesPreloader.preload_feedback!(vulnerability_occurrences)

        present vulnerability_occurrences,
                with: ::Vulnerabilities::OccurrenceEntity,
                request: GrapeRequestProxy.new(request, current_user)
      end
    end
  end
end
