# frozen_string_literal: true

module ReleaseTools
  module Security
    class ComponentsUpdateTask
      include ::SemanticLogger::Loggable

      CouldNotUpdateError = Class.new(StandardError)

      PIPELINE_SCHEDULE_ID = 112

      # @param action [Sym] - Accepts :enable or :disable
      def initialize(action:)
        @project = ReleaseTools::Project::ReleaseTools
        @client = ReleaseTools::GitlabOpsClient
        @action = action
      end

      def execute
        logger.info('Toggling components update pipeline schedule', description: pipeline_schedule.description, action: action)

        return if SharedStatus.dry_run?

        take_ownership_of_pipeline
        update_pipeline_schedule
        send_slack_notification(:success)
      rescue StandardError => ex
        logger.fatal(failure_message, error: ex)
        send_slack_notification(:failed)

        raise CouldNotUpdateError
      end

      private

      attr_reader :project, :client, :action

      def pipeline_schedule
        Retriable.with_context(:api) do
          client
            .pipeline_schedule(project, PIPELINE_SCHEDULE_ID)
        end
      end

      def take_ownership_of_pipeline
        logger.info('Taking ownership of the pipeline schedule', pipeline_schedule: PIPELINE_SCHEDULE_ID)

        Retriable.with_context(:api) do
          client.pipeline_schedule_take_ownership(
            project,
            PIPELINE_SCHEDULE_ID
          )
        end
      end

      def update_pipeline_schedule
        Retriable.with_context(:api) do
          client.edit_pipeline_schedule(
            project.ops_path,
            PIPELINE_SCHEDULE_ID,
            active: enabling_components_update_task?
          )
        end
      end

      def send_slack_notification(status)
        ReleaseTools::Slack::ReleaseJobEndNotifier.new(
          job_type: job_type,
          status: status,
          release_type: :patch
        ).send_notification
      end

      def job_type
        if enabling_components_update_task?
          'Enable components update task'
        else
          'Disable components update task'
        end
      end

      def enabling_components_update_task?
        action == :enable
      end

      def failure_message
        <<~MSG
          Toggling components update task failed. This job may be retried. If this job continues to fail,
          the #{pipeline_schedule.description} schedule can be manually updated at
          https://ops.gitlab.net/gitlab-org/release/tools/-/pipeline_schedules.
        MSG
      end
    end
  end
end
