# frozen_string_literal: true

class VulnerabilityPresenter < Gitlab::View::Presenter::Delegated
  presents :vulnerability

  def links
    vulnerability.links.map(&:with_indifferent_access)
  end

  def remediations
    vulnerability.remediations.to_a.compact.map(&:with_indifferent_access)
  end

  def location_text
    return file unless line

    "#{file}:#{line}"
  end

  def location_link_with_raw_path
    location_link_for(raw_path)
  end

  def location_link
    location_link_for(blob_path)
  end

  def raw_path
    return unless file

    path_with_line_number(project_raw_path(vulnerability.project, File.join(pipeline_branch, file)))
  end

  def blob_path
    return unless file

    path_with_line_number(vulnerability.blob_path)
  end

  def scanner
    finding.scanner || {}
  end

  def scan
    finding.scan || {}
  end

  def jira_issue_description
    ApplicationController.render(
      template: 'vulnerabilities/jira_issue_description.md.erb',
      locals: { vulnerability: self }
    )
  end

  def description
    vulnerability.description || finding.description
  end

  private

  def location_link_for(path)
    return location_text unless path

    "#{root_url}#{path}"
  end

  def pipeline_branch
    finding.pipelines&.last&.sha || project.default_branch
  end

  def path_with_line_number(path)
    return unless path

    path = path.gsub(/^\//, '')

    add_line_numbers(path, finding.location['start_line'], finding.location['end_line'])
  end

  def root_url
    Gitlab::Routing.url_helpers.root_url
  end

  def line
    finding.location.dig("start_line")
  end

  def file
    finding.location.dig("file")
  end

  def add_line_numbers(path, start_line, end_line)
    return path unless start_line

    path.tap do |complete_path|
      complete_path << "#L#{start_line}"
      complete_path << "-#{end_line}" if end_line != start_line
    end
  end
end
