# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Visits::MergeService do
  let(:user) { create(:user) }
  let(:place) { create(:place) }

  let(:visit1) do
    create(:visit,
           user: user,
           place: place,
           started_at: 2.days.ago,
           ended_at: 1.day.ago,
           duration: 1440,
           name: 'Visit 1',
           status: 'suggested')
  end

  let(:visit2) do
    create(:visit,
           user: user,
           place: place,
           started_at: 1.day.ago,
           ended_at: Time.current,
           duration: 1440,
           name: 'Visit 2',
           status: 'suggested')
  end

  let!(:point1) { create(:point, user: user, visit: visit1) }
  let!(:point2) { create(:point, user: user, visit: visit2) }

  describe '#call' do
    context 'with valid visits' do
      it 'merges visits successfully' do
        service = described_class.new([visit1, visit2])
        result = service.call

        expect(result).to be_persisted
        expect(result.id).to eq(visit1.id)
        expect(result.started_at).to eq(visit1.started_at)
        expect(result.ended_at).to eq(visit2.ended_at)
        expect(result.status).to eq('confirmed')
        expect(result.points.count).to eq(2)
      end

      it 'deletes the second visit' do
        service = described_class.new([visit1, visit2])
        service.call

        expect { visit2.reload }.to raise_error(ActiveRecord::RecordNotFound)
      end

      it 'creates a combined name for the merged visit' do
        visit1_name = visit1.name
        visit2_name = visit2.name
        service = described_class.new([visit1, visit2])
        result = service.call

        expected_name = "#{visit1_name}, #{visit2_name}"
        expect(result.name).to eq(expected_name)
      end

      it 'calculates the correct duration' do
        service = described_class.new([visit1, visit2])
        result = service.call

        # Total duration should be from earliest start to latest end
        expected_duration = ((visit2.ended_at - visit1.started_at) / 60).round
        expect(result.duration).to eq(expected_duration)
      end
    end

    context 'with less than 2 visits' do
      it 'returns nil and adds an error' do
        service = described_class.new([visit1])
        result = service.call

        expect(result).to be_nil
        expect(service.errors).to include('At least 2 visits must be selected for merging')
      end
    end

    context 'when a database error occurs' do
      before do
        allow(visit1).to receive(:update!).and_raise(ActiveRecord::RecordInvalid.new(visit1))
        allow(visit1).to receive_message_chain(:errors, :full_messages, :join).and_return('Error message')
      end

      it 'handles ActiveRecord errors' do
        service = described_class.new([visit1, visit2])
        result = service.call

        expect(result).to be_nil
        expect(service.errors).to include('Error message')
      end
    end
  end
end
