require "rails_helper"

RSpec.describe ZoomNotificationsController, type: :controller do
  render_views

  let!(:zoom_meeting) { create(:zoom_meeting, api_meeting_id: 'meeting_id') }

  let(:started_status) { {event: 'meeting.started', payload: {object: {id: 'meeting_id' }}} }
  let(:ended_status) {  {event: 'meeting.ended', payload: {object: {id: 'meeting_id' }}} }
  let(:wrong_meeting_id) { {event: 'meeting.started', payload: {object: {id: 'wrong_id' }}} }

  let(:recording_complete) { {event: 'recording.completed', payload: {object: {id: 'meeting_id', recording_files: [Object.new]}}} }

  let(:authorization_header) { {'Authorization' => 'xxx-xxx-xxx'} }
  let(:wrong_authorization_header) { {'Authorization' => 'yyy-yyy-yyy'} }

  before do
    allow(ENV).to receive(:[]).with('ZOOM_VERIFICATION_TOKEN').and_return('xxx-xxx-xxx')
  end

  describe '#create' do
    context 'with no authorization key' do
      it 'raises 403 response' do
        post :create, params: started_status
        expect(response).to have_http_status(403)
      end
    end

    context 'with wrong authorization key' do
      it 'raises 403 response' do
        request.headers.merge!(wrong_authorization_header)
        post :create, params: started_status
        expect(response).to have_http_status(403)
      end
    end

    context 'authorized' do
      before do
        request.headers.merge!(authorization_header)
      end

      context 'user hooks' do
        before(:each) { ZoomUser.create api_id: 'zoom_user_id' }

        it 'deletes the user from db if user.deleted is passed with existing user id' do
          expect {
            post :create, params: {event: 'user.deleted', payload: {object: {id: 'zoom_user_id'}}}
          }.to change { ZoomUser.count }.by(-1)
        end

        it 'does not do anything if user.deleted is passed with non-existing user' do
          expect {
            post :create, params: {event: 'user.deleted', payload: {object: {id: 'wrong-user-id'}}}
          }.not_to change { ZoomUser.count }
        end
      end

      context 'meeting hooks' do
        context 'with wrong meeting id' do
          it 'raises RecordNotFound' do
            expect {
              post :create, params: wrong_meeting_id
            }.to raise_error(ActiveRecord::RecordNotFound)
          end
        end

        context 'with right meeting id' do
          it 'responds with 200' do
            post :create, params: started_status

            expect(response).to have_http_status(200)
          end

          it 'assigns the zoom meeting' do
            post :create, params: started_status

            expect(assigns(:zoom_meeting)).to eq(zoom_meeting)
          end

          it 'updates the zoom_meeting when started status is received in notification' do
            post :create, params: started_status

            expect(zoom_meeting.reload).to be_started
          end

          it 'updates the zoom_meeting when ended status is received in notification' do
            post :create, params: ended_status

            expect(zoom_meeting.reload).to be_ended
          end

          it 'updates the recording when recording complete notification is received' do
            expect(AttachRecordingToZoomMeetingJob).to receive(:perform_later)

            post :create, params: recording_complete
          end
        end
      end
    end
  end
end
