# frozen_string_literal: true

class Vulnerability < ApplicationRecord
  include CacheMarkdownField
  include Redactable
  include StripAttribute

  cache_markdown_field :title, pipeline: :single_line
  cache_markdown_field :description, issuable_state_filter_enabled: true

  strip_attributes :title

  redact_field :description

  belongs_to :project # keep this association named 'project' for correct work of markdown cache
  belongs_to :milestone
  belongs_to :epic

  belongs_to :author, class_name: 'User' # keep this association named 'author' for correct work of markdown cache
  belongs_to :updated_by, class_name: 'User'
  belongs_to :last_edited_by, class_name: 'User'
  belongs_to :resolved_by, class_name: 'User'
  belongs_to :closed_by, class_name: 'User'

  has_many :findings, class_name: 'Vulnerabilities::Occurrence', inverse_of: :vulnerability
  has_many :issue_links, class_name: 'Vulnerabilities::IssueLink', inverse_of: :vulnerability
  has_many :related_issues, through: :issue_links, source: :issue do
    def with_vulnerability_links
      select('issues.*, vulnerability_issue_links.id AS vulnerability_link_id, '\
             'vulnerability_issue_links.link_type AS vulnerability_link_type')
    end
  end

  enum state: { opened: 1, closed: 2, resolved: 3 }
  enum severity: Vulnerabilities::Occurrence::SEVERITY_LEVELS, _prefix: :severity
  enum confidence: Vulnerabilities::Occurrence::CONFIDENCE_LEVELS, _prefix: :confidence
  enum report_type: Vulnerabilities::Occurrence::REPORT_TYPES

  validates :project, :author, :title, :severity, :confidence, :report_type, presence: true

  # at this stage Vulnerability is not an Issuable, has some important attributes (and their constraints) in common
  validates :title, length: { maximum: Issuable::TITLE_LENGTH_MAX }
  validates :title_html, length: { maximum: Issuable::TITLE_HTML_LENGTH_MAX }, allow_blank: true
  validates :description, length: { maximum: Issuable::DESCRIPTION_LENGTH_MAX }, allow_blank: true
  validates :description_html, length: { maximum: Issuable::DESCRIPTION_HTML_LENGTH_MAX }, allow_blank: true

  scope :with_findings, -> { includes(:findings) }

  # There will only be one finding associated with a vulnerability for the foreseeable future
  def finding
    findings.first
  end
end
