# frozen_string_literal: true

module VulnerabilityFilters
  extend ActiveSupport::Concern

  included do
    before_action :check_bdsa_visible, only: %i[index recent_version_chart filter]
    before_action :set_project_or_fail, except: [:filter]
    before_action :find_best_security_set, except: [:filter]
    before_action :find_all_releases, only: [:index]
    before_action :set_default_filter_period_param, only: [:index]
    before_action :find_vulnerability_data, only: [:index]
  end

  private

  def find_best_security_set
    @best_security_set = @project.best_project_security_set
  end

  def find_all_releases
    @releases = @best_security_set.releases if @best_security_set
  end

  def find_vulnerability_data
    return if @releases.blank?

    find_release
    find_minor_versions
    find_vulnerabilities
  end

  def find_release
    @release = @releases.find_by(id: filter_version_param) ||
               @best_security_set.matching_releases(filter_major_version_param).latest ||
               @releases.latest
  end

  def find_minor_versions
    @minor_versions = if filter_major_version_param.present?
                        @release.minor_versions.sort_by_release_date
                      else
                        @releases.sort_by_release_date
                      end
    @minor_versions = @minor_versions.select_within_years(filter_period_param) if filter_period_param.present?
    reset_release
  end

  def find_vulnerabilities
    return unless filter_version_param

    filter = { severity: filter_severity_param, type: params[:filter][:type] }
    order = { col: sort_col_param, direction: (params[:sort] || {}).fetch(:direction, 'ASC') }

    @vulnerabilities = @bdsa_visible ? Vulnerability : Vulnerability.where('cve_id not like ?', 'BDSA%')
    @vulnerabilities = @vulnerabilities.details(filter_version_param, filter: filter, sort: order)
                                       .paginate(page: page_param, per_page: 10)
  end

  def set_default_filter_period_param
    return check_filter_period_param if filter_period_param

    set_filter_period_param
    vul = @best_security_set.try(:oldest_vulnerability)
    return unless @releases.present? && vul

    if vul.years_ago?(5)
      check_releases_and_set_period(3)
    else
      check_releases_and_set_period(1) || check_releases_and_set_period(3)
    end
  end

  def check_releases_and_set_period(year)
    return if @releases.select_within_years(year).none?

    set_filter_period_param("#{year}yr", year)
    true
  end

  def set_filter_period_param(label = 'All', year = '')
    @default_timespan = label
    params[:filter] ||= {}
    params[:filter][:period] = year
  end

  def check_filter_period_param
    return set_filter_period_param if filter_period_param.empty?

    set_filter_period_param("#{filter_period_param}yr", filter_period_param)
  end

  def reset_release
    return unless filter_version_param.blank? && @minor_versions.first

    @release = @minor_versions.first
    params[:filter] = {} unless params.key?(:filter)
    params[:filter][:version] = @release.id
  end

  def check_bdsa_visible
    @bdsa_visible = current_user.access.admin? || ENV['BDSA_ENABLED'] == 'true'
  end
end
