require 'rails_helper'

describe Whatsapp::ChannelCreationService do
  let(:account) { create(:account) }
  let(:waba_info) { { waba_id: 'test_waba_id', business_name: 'Test Business' } }
  let(:phone_info) do
    {
      phone_number_id: 'test_phone_id',
      phone_number: '+1234567890',
      verified: true,
      business_name: 'Test Business'
    }
  end
  let(:access_token) { 'test_access_token' }
  let(:service) { described_class.new(account, waba_info, phone_info, access_token) }

  describe '#perform' do
    before do
      # Stub the webhook teardown service to prevent HTTP calls during cleanup
      teardown_service = instance_double(Whatsapp::WebhookTeardownService)
      allow(Whatsapp::WebhookTeardownService).to receive(:new).and_return(teardown_service)
      allow(teardown_service).to receive(:perform)

      # Clean up any existing channels to avoid phone number conflicts
      Channel::Whatsapp.destroy_all

      # Stub the webhook setup service to prevent HTTP calls during tests
      webhook_service = instance_double(Whatsapp::WebhookSetupService)
      allow(Whatsapp::WebhookSetupService).to receive(:new).and_return(webhook_service)
      allow(webhook_service).to receive(:perform)

      # Stub the provider validation and sync_templates
      allow(Channel::Whatsapp).to receive(:new).and_wrap_original do |method, *args|
        channel = method.call(*args)
        allow(channel).to receive(:validate_provider_config)
        allow(channel).to receive(:sync_templates)
        channel
      end
    end

    context 'when channel does not exist' do
      it 'creates a new channel' do
        expect { service.perform }.to change(Channel::Whatsapp, :count).by(1)
      end

      it 'creates channel with correct attributes' do
        channel = service.perform
        expect(channel.phone_number).to eq('+1234567890')
        expect(channel.provider).to eq('whatsapp_cloud')
        expect(channel.provider_config['api_key']).to eq(access_token)
        expect(channel.provider_config['phone_number_id']).to eq('test_phone_id')
        expect(channel.provider_config['business_account_id']).to eq('test_waba_id')
        expect(channel.provider_config['source']).to eq('embedded_signup')
      end

      it 'creates an inbox for the channel' do
        channel = service.perform
        inbox = channel.inbox
        expect(inbox).not_to be_nil
        expect(inbox.name).to eq('Test Business WhatsApp')
        expect(inbox.account).to eq(account)
      end
    end

    context 'when channel already exists for the phone number' do
      let(:different_account) { create(:account) }

      before do
        create(:channel_whatsapp, account: different_account, phone_number: '+1234567890',
                                  provider: 'whatsapp_cloud', sync_templates: false, validate_provider_config: false)
      end

      it 'raises an error even if the channel belongs to a different account' do
        expect { service.perform }.to raise_error(
          RuntimeError,
          I18n.t('errors.whatsapp.phone_number_already_exists', phone_number: '+1234567890')
        )
      end
    end

    context 'when required parameters are missing' do
      it 'raises error when account is nil' do
        service = described_class.new(nil, waba_info, phone_info, access_token)
        expect { service.perform }.to raise_error(ArgumentError, 'Account is required')
      end

      it 'raises error when waba_info is nil' do
        service = described_class.new(account, nil, phone_info, access_token)
        expect { service.perform }.to raise_error(ArgumentError, 'WABA info is required')
      end

      it 'raises error when phone_info is nil' do
        service = described_class.new(account, waba_info, nil, access_token)
        expect { service.perform }.to raise_error(ArgumentError, 'Phone info is required')
      end

      it 'raises error when access_token is blank' do
        service = described_class.new(account, waba_info, phone_info, '')
        expect { service.perform }.to raise_error(ArgumentError, 'Access token is required')
      end
    end

    context 'when business_name is in different places' do
      context 'when business_name is only in phone_info' do
        let(:waba_info) { { waba_id: 'test_waba_id' } }

        it 'uses business_name from phone_info' do
          channel = service.perform
          expect(channel.inbox.name).to eq('Test Business WhatsApp')
        end
      end

      context 'when business_name is only in waba_info' do
        let(:phone_info) do
          {
            phone_number_id: 'test_phone_id',
            phone_number: '+1234567890',
            verified: true
          }
        end

        it 'uses business_name from waba_info' do
          channel = service.perform
          expect(channel.inbox.name).to eq('Test Business WhatsApp')
        end
      end
    end
  end
end
