# frozen_string_literal: true

module ReleaseTools
  module UpdatePaths
    class DynamicPipeline < DynamicPipelineBase
      DEV_OMNIBUS_REGISTRY = 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ee'

      def initialize(version)
        @version = ReleaseTools::Version.new(version)
      end

      private

      attr_reader :version

      def stages
        {
          'stages' => [
            main_stage_name,
            notification_stage_name
          ]
        }
      end

      def jobs
        {
          job_name => main_job,
          'notification_job_success' => notification_job_success,
          'notification_job_failed' => notification_job_failed
        }
      end

      def main_job
        {
          'stage' => main_stage_name,
          'image' => 'registry.gitlab.com/gitlab-org/gitlab-build-images/debian-bookworm-ruby-3.2.5:docker-24.0.5',
          'services' => ['docker:${DOCKER_VERSION}-dind'],
          'variables' => {
            'DOCKER_VERSION' => '24.0.5',
            'DOCKER_HOST' => 'tcp://docker:2376',
            'DOCKER_TLS_VERIFY' => '1',
            'DOCKER_TLS_CERTDIR' => '/certs',
            'DOCKER_CERT_PATH' => '/certs/client',
            'GITLAB_QA_DEV_ACCESS_TOKEN' => '$RELEASE_BOT_DEV_TOKEN',
            'QA_GENERATE_ALLURE_REPORT' => 'true',
            'QA_CAN_TEST_PRAEFECT' => 'false',
            'QA_INTERCEPT_REQUESTS' => 'true',
            'QA_ARTIFACTS_DIR' => '$CI_PROJECT_DIR',
            'QA_ALLOW_LOCAL_REQUESTS' => 'true',
            'GITLAB_LICENSE_MODE' => 'test',
            'FF_NETWORK_PER_BUILD' => 'true'

          },
          'tags' => %w[docker],
          'script' => [
            'git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/gitlab-org/gitlab-qa.git',
            'cd gitlab-qa',
            'bundle install',
            "bundle exec gitlab-qa Test::Omnibus::UpdateFromPrevious #{target_image} #{source_version} #{test_type} -- --tag health_check"
          ],
          'extends' => [
            '.common-ci-tokens'
          ],
          'artifacts' => {
            'when' => 'always',
            'expire_in' => '30d',
            'paths' => ['gitlab-qa-run-*'],
            'reports' => {
              'junit' => 'gitlab-qa-run-*/**/rspec-*.xml'
            }
          }
        }
      end

      def notification_job_base(status)
        {
          'image' => "$CI_REGISTRY_IMAGE/base:$CI_DEFAULT_BRANCH",
          'stage' => notification_stage_name,
          'script' => [
            "source scripts/setup_ssh.sh",
            "source scripts/setup_git.sh",
            "bundle exec rake \"release:update_paths:finish_notification[#{previous_version},#{version},#{status}]\""
          ],
          'extends' => [
            '.with-bundle',
            '.common-ci-tokens'
          ],
          'when' => status == 'success' ? 'on_success' : 'on_failure'
        }
      end

      def notification_job_success
        notification_job_base('success')
      end

      def notification_job_failed
        notification_job_base('failed')
      end

      def previous_version
        @previous_version ||= ReleaseTools::Version.new(
          if version.monthly?
            GitlabReleasesGemClient.latest_patch_for_version(version.previous_minor)
          else
            # At the time of running, the tested version is not yet registered on
            # version.gitlab.com, so the latest patch version is the previous version we want
            # to test the update path from.
            GitlabReleasesGemClient.latest_patch_for_version(version)
          end
        )
      end

      def main_stage_name
        if version.monthly?
          "patch-to-monthly"
        elsif previous_version.monthly?
          "monthly-to-patch"
        else
          "patch-to-patch"
        end
      end

      def notification_stage_name
        "finish_notification"
      end

      def job_name
        "#{previous_version}-to-#{version}".tr('.', '-')
      end

      def test_type
        return "minor" if version.monthly?

        "patch"
      end

      # When updating from a patch version to a monthly version, we use a different scenario "minor" where the
      # previous version is also the same as the target version:
      # bundle exec gitlab-qa Test::Omnibus::UpdateFromPrevious dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ee:17.10.0-ee.0 17.10.0 minor -- --tag health_check
      def source_version
        version.monthly? ? version : previous_version
      end

      # UpdatePaths testing is between tagging and publish, so the new version is not yet published to DockerHub,
      # but only on the Dev Omnibus GitLab registry.
      def target_image
        "#{DEV_OMNIBUS_REGISTRY}:#{version.to_docker(ee: true)}"
      end
    end
  end
end
