# frozen_string_literal: true

require 'date'
require 'erb'
require 'pathname'

module Gitlab
  module QA
    module Scenario
      module Test
        module Integration
          class ContinuousVulnerabilityScanning < Scenario::Template
            def initialize
              @network = Runtime::Env.docker_network
              @tag = 'secure_cvs'
            end

            def perform(release, *rspec_args)
              Component::Gitlab.perform do |gitlab|
                setup_and_run_tests(gitlab, release, *rspec_args)
              end
            end

            private

            def setup_and_run_tests(gitlab, release, *rspec_args)
              set_up_gitlab(gitlab, release)
              gitlab.instance do
                place_new_vulnerabilities(gitlab)
                run_specs(gitlab, *rspec_args)
              end
            end

            def set_up_gitlab(gitlab, release)
              gitlab.release = QA::Release.new(release)
              gitlab.name = 'gitlab'
              gitlab.network = @network
            end

            def place_new_vulnerabilities(gitlab)
              write_vulnerabilities(gitlab, generate_filepath, generate_vulnerabilities)
              start_advisory_sync_worker(gitlab)
            end

            def generate_vulnerabilities
              template = File.read(File.expand_path('../../../../../../fixtures/cvs/vulnerabilities_template.erb', __dir__))
              ERB.new(template).result(binding)
            end

            def generate_filepath
              File.join(
                "/opt/gitlab/embedded/service/gitlab-rails/vendor/package_metadata/advisories/v2/rubygem/#{Time.now.to_i}",
                '000000000.ndjson'
              )
            end

            def write_vulnerabilities(gitlab, filepath, content)
              gitlab.docker.exec(gitlab.name, "mkdir -p #{File.dirname(filepath)}")
              gitlab.docker.write_files(gitlab.name) { |f| f.write(filepath, content, false) }
            end

            def start_advisory_sync_worker(gitlab)
              gitlab.docker.exec(gitlab.name, "PM_SYNC_IN_DEV=true gitlab-rails runner 'loop do PackageMetadata::AdvisoriesSyncWorker.new.perform; sleep 30; end' &")
            end

            def run_specs(gitlab, *rspec_args)
              Runtime::Logger.info('Running Continuous Vulnerability Scanning spec...')
              rspec_args << "--" unless rspec_args.include?('--')
              rspec_args << "--tag" << @tag
              run_spec_component(gitlab, rspec_args)
            end

            def run_spec_component(gitlab, rspec_args)
              Component::Specs.perform do |specs|
                specs.suite = 'Test::Instance::All'
                specs.release = gitlab.release
                specs.network = gitlab.network
                specs.args = [gitlab.address, *rspec_args]
              end
            end
          end
        end
      end
    end
  end
end