# frozen_string_literal: true

require 'rake_helper'

describe 'monthly tasks', :rake do
  describe 'finalize:start', task: 'monthly:finalize:start' do
    it 'starts the finalize stage' do
      expect(ReleaseTools::Slack::ReleasePipelineStartNotifier).to receive(:new).with(release_type: :monthly, stage: :finalize)
        .and_return(instance_double(ReleaseTools::Slack::ReleasePipelineStartNotifier, execute: true))

      task.invoke
    end
  end

  describe 'update_protected_branches', task: 'monthly:finalize:update_protected_branches' do
    it 'disables omnibus nightly' do
      expect(ReleaseTools::Monthly::Finalize::UpdateProtectedBranches).to receive(:new)
        .and_return(instance_double(ReleaseTools::Monthly::Finalize::UpdateProtectedBranches, execute: true))

      task.invoke
    end
  end

  describe 'finalize:create_release_status_metric', task: 'monthly:finalize:create_release_status_metric' do
    it 'creates a new release status metric with open status' do
      expect(ReleaseTools::Metrics::MonthlyReleaseStatus).to receive(:new).with(status: :open)
        .and_return(instance_double(ReleaseTools::Metrics::MonthlyReleaseStatus, execute: true))

      task.invoke
    end
  end

  describe 'finalize:create_version', task: 'monthly:finalize:create_version' do
    before do
      allow(GitlabReleases)
        .to receive(:active_version)
        .and_return("17.0.0")
    end

    it 'creates a new version on version.gitlab.com' do
      expect(ReleaseTools::Services::CreateVersionService)
        .to receive(:new)
        .with(version: "17.0.0")
        .and_return(instance_double(ReleaseTools::Services::CreateVersionService, execute: true))
      task.invoke
    end
  end

  describe 'initial_rc:start', task: 'monthly:initial_rc:start' do
    it 'starts the initial RC creation stage' do
      expect(ReleaseTools::Slack::ReleasePipelineStartNotifier).to receive(:new).with(release_type: :monthly, stage: :initial_rc)
        .and_return(instance_double(ReleaseTools::Slack::ReleasePipelineStartNotifier, execute: true))

      task.invoke
    end
  end

  describe 'tag_day:check_omnibus_packages_tagging', task: 'monthly:tag_day:check_omnibus_packages_tagging' do
    before do
      allow(GitlabReleases)
        .to receive(:active_version)
        .and_return("17.0.0")
    end

    it 'calls ReleaseTools::Services::OmnibusPackages::Tagging with the correct version' do
      expect(ReleaseTools::Services::OmnibusPackages::Tagging)
        .to receive(:new)
        .with(version: "17.0.0")
        .and_return(instance_double(ReleaseTools::Services::OmnibusPackages::Tagging, execute: true))
      task.invoke
    end
  end

  describe 'tag_day:ensure_stable_branches_green', task: 'monthly:tag_day:ensure_stable_branches_green' do
    it 'ensures stable branches are green' do
      expect(ReleaseTools::Monthly::TagDay::ComponentBranchVerifier).to receive(:new)
        .and_return(instance_double(ReleaseTools::Monthly::TagDay::ComponentBranchVerifier, execute: true))
      task.invoke
    end
  end

  describe 'release_day:start', task: 'monthly:release_day:start' do
    it 'starts the release day stage' do
      expect(ReleaseTools::Slack::ReleasePipelineStartNotifier).to receive(:new).with(release_type: :monthly, stage: :release_day)
        .and_return(instance_double(ReleaseTools::Slack::ReleasePipelineStartNotifier, execute: true))

      task.invoke
    end
  end

  describe 'release_day:notify_release_publish', task: 'monthly:release_day:notify_release_publish' do
    it 'sends a slack notification that the release packages will be published' do
      expect(ReleaseTools::Monthly::ReleaseDay::NotifyReleasePublish).to receive(:new)
        .and_return(instance_double(ReleaseTools::Monthly::ReleaseDay::NotifyReleasePublish, execute: true))
      task.invoke
    end
  end

  describe 'release_day:start_publish', task: 'monthly:release_day:start_publish' do
    it 'starts the release day stage' do
      expect(ReleaseTools::Slack::ReleasePipelineStartNotifier).to receive(:new).with(release_type: :monthly, stage: :publish)
        .and_return(instance_double(ReleaseTools::Slack::ReleasePipelineStartNotifier, execute: true))

      task.invoke
    end
  end

  describe 'release_day:publish', task: 'monthly:release_day:publish' do
    let(:version) { instance_double(ReleaseTools::Version) }

    before do
      allow(ReleaseTools::Version).to receive(:new).and_return(version)
      allow(GitlabReleases).to receive(:active_version).and_return('16.0.0')
    end

    it 'starts the release day stage' do
      expect(ReleaseTools::Tasks::Release::Publish).to receive(:new)
        .with(version)
        .and_return(instance_double(ReleaseTools::Tasks::Release::Publish, execute: true))

      task.invoke
    end
  end

  describe 'verify:start', task: 'monthly:verify:start' do
    it 'starts the verification stage' do
      expect(ReleaseTools::Slack::ReleasePipelineStartNotifier).to receive(:new).with(release_type: :monthly, stage: :verify)
        .and_return(instance_double(ReleaseTools::Slack::ReleasePipelineStartNotifier, execute: true))

      task.invoke
    end
  end

  describe 'verify:check_omnibus_packages_publishing', task: 'monthly:verify:check_omnibus_packages_publishing' do
    it 'Check packages are published by checking `check-packages-availability` job' do
      allow(GitlabReleases).to receive(:active_version).and_return("16.0")
      allow(ReleaseTools::Version).to receive(:new).with(GitlabReleases.active_version).and_return("16.0.0")

      version = ReleaseTools::Version.new(GitlabReleases.active_version)
      expect(ReleaseTools::Services::OmnibusPackages::Publishing).to receive(:new).with(version: version)
        .and_return(instance_double(ReleaseTools::Services::OmnibusPackages::Publishing, execute: true))
      task.invoke
    end
  end

  describe 'verify:check_docker_tags', task: 'monthly:verify:check_docker_tags' do
    it 'checks for docker tags on hub.docker.com' do
      allow(GitlabReleases).to receive(:active_version).and_return("16.0")
      allow(ReleaseTools::Version).to receive(:new).with(GitlabReleases.active_version).and_return("16.0.0")

      version = ReleaseTools::Version.new(GitlabReleases.active_version)
      expect(ReleaseTools::DockerHub::Verifier).to receive(:new).with(release_type: :monthly, version: version)
        .and_return(instance_double(ReleaseTools::DockerHub::Verifier, execute: true))

      task.invoke
    end
  end

  describe 'update_paths:generate_dynamic_pipeline', task: 'monthly:update_paths:generate_dynamic_pipeline' do
    let(:dynamic_pipeline) { instance_double(ReleaseTools::UpdatePaths::DynamicPipeline) }
    let(:latest_version) { '1.2.1' }

    before do
      allow(GitlabReleases).to receive(:active_version).and_return(latest_version)
      allow(ReleaseTools::Version).to receive(:new).with(GitlabReleases.active_version).and_return(latest_version)
      allow(ReleaseTools::UpdatePaths::DynamicPipeline).to receive(:new).with(latest_version).and_return(dynamic_pipeline)
      allow(dynamic_pipeline).to receive(:generate)

      allow(File).to receive(:write)
    end

    it 'calls generate method on the ReleaseTools::UpdatePaths::DynamicPipeline instance' do
      expect(ReleaseTools::UpdatePaths::DynamicPipeline).to receive(:new).with(latest_version).and_return(dynamic_pipeline)
      expect(dynamic_pipeline).to receive(:generate)
      task.invoke
    end

    it 'writes the generated YAML content to dynamic-gitlab-ci.yml' do
      expect(File).to receive(:write).with('dynamic-gitlab-ci.yml', dynamic_pipeline.generate)
      task.invoke
    end
  end
end
