# frozen_string_literal: true

module VulnerabilityExports
  class ExportService
    include ::Gitlab::ExclusiveLeaseHelpers

    LEASE_TTL = 1.hour
    LEASE_NAMESPACE = "vulnerability_exports_export"
    EXPORTERS = {
      'csv' => VulnerabilityExports::Exporters::CsvService
    }.freeze

    def self.export(vulnerability_export)
      new(vulnerability_export).export
    end

    def initialize(vulnerability_export)
      self.vulnerability_export = vulnerability_export
    end

    def export
      in_lock(lease_key, ttl: LEASE_TTL) do
        generate_export if vulnerability_export.created?
      end
    end

    private

    attr_accessor :vulnerability_export

    delegate :exportable, to: :vulnerability_export, private: true
    delegate :format, to: :vulnerability_export, private: true

    def lease_key
      "#{LEASE_NAMESPACE}:#{vulnerability_export.id}"
    end

    def generate_export
      vulnerability_export.start!
      generate_export_file
      vulnerability_export.finish!
    rescue => error
      vulnerability_export.failed!
      raise(error)
    ensure
      schedule_export_deletion
    end

    def generate_export_file
      exporter.generate { |f| vulnerability_export.file = f }
      vulnerability_export.file.filename = filename
    end

    def exporter
      EXPORTERS[format].new(vulnerabilities)
    end

    def vulnerabilities
      Security::VulnerabilitiesFinder.new(exportable).execute.with_findings_and_scanner
    end

    def schedule_export_deletion
      VulnerabilityExports::ExportDeletionWorker.perform_in(1.hour, vulnerability_export.id)
    end

    def filename
      [
        exportable.full_path.parameterize,
        '_vulnerabilities_',
        Time.now.utc.strftime('%FT%H%M'),
        '.',
        format
      ].join
    end
  end
end
