# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Trips::CalculateCountriesJob, type: :job do
  describe '#perform' do
    let(:user) { create(:user) }
    let(:trip) { create(:trip, user: user) }
    let(:distance_unit) { 'km' }
    let(:points) do
      [
        create(:point, user: user, country_name: 'Germany', timestamp: trip.started_at.to_i + 1.hour),
        create(:point, user: user, country_name: 'France', timestamp: trip.started_at.to_i + 2.hours),
        create(:point, user: user, country_name: 'Germany', timestamp: trip.started_at.to_i + 3.hours),
        create(:point, user: user, country_name: 'Italy', timestamp: trip.started_at.to_i + 4.hours)
      ]
    end

    before do
      points # Create the points
    end

    it 'finds the trip and calculates countries' do
      expect(Trip).to receive(:find).with(trip.id).and_return(trip)
      expect(trip).to receive(:calculate_countries)
      expect(trip).to receive(:save!)

      described_class.perform_now(trip.id, distance_unit)
    end

    it 'calculates unique countries from trip points' do
      described_class.perform_now(trip.id, distance_unit)

      trip.reload
      expect(trip.visited_countries).to contain_exactly('Germany', 'France', 'Italy')
    end

    it 'broadcasts the update with correct parameters' do
      expect(Turbo::StreamsChannel).to receive(:broadcast_update_to).with(
        "trip_#{trip.id}",
        target: "trip_countries",
        partial: "trips/countries",
        locals: { trip: trip, distance_unit: distance_unit }
      )

      described_class.perform_now(trip.id, distance_unit)
    end

    context 'when trip has no points' do
      let(:trip_without_points) { create(:trip, user: user) }

      it 'sets visited_countries to empty array' do
        trip_without_points.points.destroy_all
        described_class.perform_now(trip_without_points.id, distance_unit)

        trip_without_points.reload

        expect(trip_without_points.visited_countries).to eq([])
      end
    end

    context 'when points have nil country names' do
      let(:points_with_nil_countries) do
        [
          create(:point, user: user, country_name: 'Germany', timestamp: trip.started_at.to_i + 1.hour),
          create(:point, user: user, country_name: nil, timestamp: trip.started_at.to_i + 2.hours),
          create(:point, user: user, country_name: 'France', timestamp: trip.started_at.to_i + 3.hours)
        ]
      end

      before do
        # Remove existing points and create new ones with nil countries
        Point.where(user: user).destroy_all
        points_with_nil_countries
      end

      it 'filters out nil country names' do
        described_class.perform_now(trip.id, distance_unit)

        trip.reload
        expect(trip.visited_countries).to contain_exactly('Germany', 'France')
      end
    end

    context 'when trip is not found' do
      it 'raises ActiveRecord::RecordNotFound' do
        expect {
          described_class.perform_now(999999, distance_unit)
        }.to raise_error(ActiveRecord::RecordNotFound)
      end
    end

    context 'when distance_unit is different' do
      let(:distance_unit) { 'mi' }

      it 'passes the correct distance_unit to broadcast' do
        expect(Turbo::StreamsChannel).to receive(:broadcast_update_to).with(
          "trip_#{trip.id}",
          target: "trip_countries",
          partial: "trips/countries",
          locals: { trip: trip, distance_unit: 'mi' }
        )

        described_class.perform_now(trip.id, distance_unit)
      end
    end

    describe 'queue configuration' do
      it 'uses the trips queue' do
        expect(described_class.queue_name).to eq('trips')
      end
    end
  end
end
