/**
 * @author: Hemal
 * File: getViewPropertyAvailability.test.ts
 * Purpose: Unit tests for `getViewPropertyAvailability` thunk (defined inline).
 * Description:
 * - Defines custom thunk inside test file.
 * - Mocks apiClient.
 * - Covers scenarios with and without bookingId and callback.
 */

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('getViewPropertyAvailability thunk', () => {
    const mockDispatch = jest.fn();

    /**
     * Asynchronous thunk action for View Property Availability process.
     * @param payload - The data required for booking View Property Availability.
     * @param callback - Optional callback function that receives API response data.
     * @returns A thunk function that dispatches actions based on API response.
     */
    const getViewPropertyAvailability =
        (
            payload: { propertyId: string; bookingId?: string },
            callback?: (data: any) => void
        ) =>
            async (dispatch: any) => {
                try {
                    dispatch({ type: 'REQUEST_VIEW_PROPERTY_AVAILABILITY' });
                    const response = await apiClient.post(API_ENDPOINTS.BOOKING_VIEW_PROPERTY_AVAILABILITY, payload);
                    callback && callback(response?.data);
                    dispatch({
                        type: 'SUCCESS_VIEW_PROPERTY_AVAILABILITY',
                        payload: response?.data,
                    });
                } catch (error) {
                    dispatch({ type: 'FAILURE_VIEW_PROPERTY_AVAILABILITY' });
                }
            };

    const basePayload = {
        propertyId: 'test-property-id',
    };

    const fullPayload = {
        propertyId: 'test-property-id',
        bookingId: 'test-booking-id',
    };

    const mockResponseData = {
        statusCode: 200,
        data: {
            propertyId: 'test-property-id',
            availableDates: ['2025-07-30', '2025-07-31'],
        },
    };

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

    // ✅ With bookingId and callback
    it('should dispatch success actions and call callback with bookingId', async () => {
        const mockCallback = jest.fn();
        mockedApi.post.mockResolvedValueOnce({ data: mockResponseData });

        await getViewPropertyAvailability(fullPayload, mockCallback)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_VIEW_PROPERTY_AVAILABILITY' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.BOOKING_VIEW_PROPERTY_AVAILABILITY, fullPayload);
        expect(mockCallback).toHaveBeenCalledWith(mockResponseData);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_VIEW_PROPERTY_AVAILABILITY',
            payload: mockResponseData,
        });
    });

    // ✅ Without bookingId and callback
    it('should dispatch success actions without bookingId and without callback', async () => {
        mockedApi.post.mockResolvedValueOnce({ data: mockResponseData });

        await getViewPropertyAvailability(basePayload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_VIEW_PROPERTY_AVAILABILITY' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.BOOKING_VIEW_PROPERTY_AVAILABILITY, basePayload);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_VIEW_PROPERTY_AVAILABILITY',
            payload: mockResponseData,
        });
    });

    // ❌ API failure
    it('should dispatch failure action on API error', async () => {
        mockedApi.post.mockRejectedValueOnce(new Error('API error'));

        await getViewPropertyAvailability(basePayload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_VIEW_PROPERTY_AVAILABILITY' });
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'FAILURE_VIEW_PROPERTY_AVAILABILITY' });
    });
});
