jest.mock('../../src/interceptor/apiClient');

import apiClient from '../../src/interceptor/apiClient';
import { API_ENDPOINTS } from '@/src/utils/commonVariables';

const mockedApi = apiClient as jest.Mocked<typeof apiClient>;

describe('getViewBooking thunk', () => {
    const mockDispatch = jest.fn();
    const mockCallback = jest.fn();

    /**
     * Asynchronous thunk action to view booking details.
     * Dispatches actions that represent the different states of the API call: request, success, or failure.
     * 
     * @param payload - An object containing the bookingId of the booking to be viewed.
     * @param callback - An optional callback function that receives the response data from the API if the call is successful.
     * 
     * Dispatches:
     * - REQUEST_VIEW_BOOKING: Before the API call to indicate loading.
     * - SUCCESS_VIEW_BOOKING: On successful API response with the booking data.
     * - FAILURE_VIEW_BOOKING: In case of an API error.
     */
    const getViewBooking =
        (payload: { bookingId: string }, callback?: (data: any) => void) =>
            async (dispatch: any) => {
                try {
                    dispatch({ type: 'REQUEST_VIEW_BOOKING' });
                    const response: any = await apiClient.post(API_ENDPOINTS.VIEW_BOOKING, payload);
                    callback && callback(response?.data);
                    dispatch({ type: 'SUCCESS_VIEW_BOOKING', payload: response?.data });
                } catch (error: any) {
                    dispatch({ type: 'FAILURE_VIEW_BOOKING' });
                    // No Toast here
                }
            };

    const payload = { bookingId: 'booking-789' };

    const mockSuccessResponse = {
        data: {
            meta: {
                status: 1,
                message: 'Booking fetched successfully',
            },
            data: {
                bookingId: 'booking-789',
                status: 'confirmed',
                guestName: 'Jane Smith',
            },
        },
    };

    beforeEach(() => {
        jest.clearAllMocks();
    });

    it('should dispatch request and success actions and call callback on success', async () => {
        mockedApi.post.mockResolvedValueOnce(mockSuccessResponse);

        await getViewBooking(payload, mockCallback)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_VIEW_BOOKING' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.VIEW_BOOKING, payload);
        expect(mockCallback).toHaveBeenCalledWith(mockSuccessResponse.data);
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'SUCCESS_VIEW_BOOKING', payload: mockSuccessResponse.data });
    });

    it('should dispatch request and failure actions and not call callback on error', async () => {
        mockedApi.post.mockRejectedValueOnce(new Error('Network error'));

        await getViewBooking(payload, mockCallback)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_VIEW_BOOKING' });
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'FAILURE_VIEW_BOOKING' });
        expect(mockCallback).not.toHaveBeenCalled();
    });
});
