# frozen_string_literal: true

RSpec.describe 'rake gdk:migrate' do
  before(:all) do
    Rake.application.rake_require('tasks/gdk')
  end

  it 'invokes its dependencies' do
    expect(task.prerequisites).to eq(%w[
      migrate:update_telemetry_settings
      migrate:mise
    ])
  end
end

RSpec.describe 'rake gdk:migrate:update_telemetry_settings' do
  let(:enabled) { false }
  let(:is_team_member) { false }
  let(:username) { 'telemetry_user' }

  before(:all) do
    Rake.application.rake_require('tasks/gdk')
  end

  before do
    stub_gdk_yaml(<<~YAML)
      telemetry:
        enabled: #{enabled}
        username: #{username.inspect}
    YAML

    allow(GDK::Telemetry).to receive(:team_member?).and_return(is_team_member)
    allow(GDK.config).to receive(:save_yaml!)
  end

  context 'when telemetry is disabled' do
    let(:enabled) { false }

    context 'and user is not a GitLab team member' do
      it 'does nothing' do
        expect(GDK::Telemetry).not_to receive(:update_settings)

        task.invoke
      end
    end

    context 'and user is a team member' do
      let(:is_team_member) { true }

      it 'enables telemetry' do
        expect(GDK::Telemetry).to receive(:update_settings).with('y')
        expect(GDK::Output).to receive(:info).with('Telemetry has been automatically enabled for you as a GitLab team member.')

        task.invoke
      end
    end
  end

  context 'when telemetry is enabled and username is not anonymized' do
    let(:enabled) { true }
    let(:generated_username) { SecureRandom.hex }

    before do
      allow(SecureRandom).to receive(:hex).and_return(generated_username)
    end

    it 'anonymizes the username' do
      expect { task.invoke }.to output(/Telemetry username has been anonymized./).to_stdout
      expect(GDK.config.telemetry.username).not_to eq(username)
      expect(GDK.config.telemetry.username).to match(/^\h{32}$/)
    end
  end
end

RSpec.describe 'rake gdk:migrate:mise' do
  let(:asdf_opt_out) { false }
  let(:mise_enabled) { false }
  let(:is_team_member) { true }
  let(:should_run_reminder) { true }
  let(:is_interactive) { true }
  let(:user_response) { 'n' }
  let(:diagnostic) { instance_double(GDK::Diagnostic::ToolVersionManager) }

  before(:all) do
    Rake.application.rake_require('tasks/gdk')
  end

  before do
    allow(GDK.config).to receive_message_chain(:asdf, :opt_out?).and_return(asdf_opt_out)
    allow(GDK.config).to receive_message_chain(:mise, :enabled).and_return(mise_enabled)
    allow(GDK::Telemetry).to receive(:team_member?).and_return(is_team_member)
    allow(GDK::ReminderHelper).to receive(:should_run_reminder?).with('mise_migration').and_return(should_run_reminder)
    allow(GDK::Output).to receive(:warn)
    allow(GDK::Output).to receive(:puts)
    allow(GDK::Output).to receive(:info)
    allow(GDK::Output).to receive_messages(interactive?: is_interactive, prompt: user_response)
    allow(GDK::Output).to receive(:prompt).and_return(user_response)
    allow(GDK::ReminderHelper).to receive(:update_reminder_timestamp!)
    allow(GDK::Diagnostic::ToolVersionManager).to receive(:new).and_return(diagnostic)
    allow(diagnostic).to receive(:detail).with(:update).and_return('Update message')
    allow(diagnostic).to receive(:correct!)
  end

  context 'when asdf is opted out' do
    let(:asdf_opt_out) { true }

    it 'skips the migration prompt' do
      expect(GDK::Output).not_to receive(:warn)
      expect(GDK::Output).not_to receive(:prompt)

      task.invoke
    end
  end

  context 'when mise is already enabled' do
    let(:mise_enabled) { true }

    it 'skips the migration prompt' do
      expect(GDK::Output).not_to receive(:warn)
      expect(GDK::Output).not_to receive(:prompt)

      task.invoke
    end
  end

  context 'when user is not a GitLab team member' do
    let(:is_team_member) { false }

    it 'skips the migration prompt' do
      expect(GDK::Output).not_to receive(:warn)
      expect(GDK::Output).not_to receive(:prompt)

      task.invoke
    end
  end

  context 'when reminder should not run' do
    let(:should_run_reminder) { false }

    it 'skips the migration prompt' do
      expect(GDK::Output).not_to receive(:warn)
      expect(GDK::Output).not_to receive(:prompt)

      task.invoke
    end
  end

  context 'when migration should be prompted' do
    context 'when environment is not interactive' do
      let(:is_interactive) { false }

      it 'displays info message and skips the migration prompt' do
        expect(GDK::Output).to receive(:info).with('Skipping mise migration prompt in non-interactive environment.')
        expect(GDK::Output).not_to receive(:prompt)

        task.invoke
      end
    end

    context 'when user accepts the migration' do
      let(:user_response) { 'y' }

      it 'runs the migration' do
        expect(GDK::Output).to receive(:prompt).with('Would you like it to switch to mise now? [y/N]')
        expect(GDK::Output).to receive(:info).with('Great! Running the mise migration now..')
        expect(diagnostic).to receive(:correct!)

        task.invoke
      end
    end

    context 'when user declines the migration' do
      let(:user_response) { 'n' }

      it 'updates the reminder timestamp' do
        expect(GDK::Output).to receive(:prompt).with('Would you like it to switch to mise now? [y/N]')
        expect(GDK::Output).to receive(:info).with("No worries. We'll remind you again in 5 days.")
        expect(GDK::ReminderHelper).to receive(:update_reminder_timestamp!).with('mise_migration')
        expect(diagnostic).not_to receive(:correct!)

        task.invoke
      end
    end
  end
end
