/**
 *  @author: Hemal
 * File: getPropertyList.test.ts
 * Purpose: This file contains unit tests for the `getPropertyList` asynchronous thunk action.
 * Description:
 * - Utilizes `jest.mock` to mock the `apiClient` module.
 * - Tests the behavior of the `getPropertyList` action, including dispatching actions and handling API responses.
 * - Verifies that the correct actions are dispatched based on the API response.
*/

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

import { API_ENDPOINTS } from '@/src/utils/commonVariables';
import apiClient from '../../src/interceptor/apiClient';
const mockedApi = apiClient as jest.Mocked<typeof apiClient>;

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

    /**
     * A thunk that handles getting property list from the API.
     * If the payload contains the key "countOnly" with a value of true, it will dispatch
     * "REQUEST_FILTER_PROPERTY_LIST" and "SUCCESS_FILTER_PROPERTY_LIST" actions. Otherwise, it will
     * dispatch "REQUEST_PROPERTY_LIST" and "SUCCESS_PROPERTY_LIST" actions.
     * In case of error, it will dispatch either "FAILURE_FILTER_PROPERTY_LIST" or "FAILURE_PROPERTY_LIST"
     * action depending on the "countOnly" key in the payload.
     * @param {object} payload - The payload containing the data required for getting property list.
     * @returns {function} - A thunk function that dispatches actions based on the API response.
     */
    const getPropertyList = (payload: { page: number; perPage: number; countOnly: boolean }) => async (dispatch: any) => {
        try {
            if (payload.countOnly) {
                dispatch({ type: 'REQUEST_FILTER_PROPERTY_LIST' });
            } else {
                dispatch({ type: 'REQUEST_PROPERTY_LIST' });
            }

            const response = await apiClient.post(API_ENDPOINTS.LIST_PROPERTY, payload);

            if (payload.countOnly) {
                dispatch({
                    type: 'SUCCESS_FILTER_PROPERTY_LIST',
                    payload: { meta: response?.data?.meta },
                });
            } else {
                dispatch({
                    type: 'SUCCESS_PROPERTY_LIST',
                    payload: {
                        data: response?.data?.data,
                        meta: response?.data?.meta,
                        page: payload.page,
                    },
                });
            }
        } catch (error: any) {
            if (payload.countOnly) {
                dispatch({ type: 'FAILURE_FILTER_PROPERTY_LIST' });
            } else {
                dispatch({ type: 'FAILURE_PROPERTY_LIST' });
            }
        }
    };

    // Mock response data
    const mockResponseData = {
        data: {
            statusCode: 200,
            data: [{ propertyId: '123', name: 'Sample Property' }],
            meta: { status: 1, message: 'Success', totalCount: 1 },
        },
    };

    // Clear mocks before each test
    beforeEach(() => {
        jest.clearAllMocks();
    });

    // Test cases when countOnly is true
    it('should dispatch success actions and call API', async () => {
        mockedApi.post.mockResolvedValueOnce(mockResponseData);

        const payload = { page: 1, perPage: 10, countOnly: false };
        await getPropertyList(payload)(mockDispatch);

        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_PROPERTY, payload);
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_PROPERTY_LIST' });
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_PROPERTY_LIST',
            payload: {
                data: mockResponseData.data.data,
                meta: mockResponseData.data.meta,
                page: 1,
            },
        });
    });

    // Test cases when countOnly is false
    it('should dispatch failure action on error', async () => {
        mockedApi.post.mockRejectedValueOnce(new Error('API failed'));
        const payload = { page: 1, perPage: 10, countOnly: true };

        await getPropertyList(payload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_FILTER_PROPERTY_LIST' });
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'FAILURE_FILTER_PROPERTY_LIST' });
    });


    it('should dispatch property list actions with minimal payload (no filters, no guests)', async () => {
        const searchBarData = {
            guestCount: false,
            isSearchClicked: true,
            activeTab: 'standard',
        };

        const payload = {
            page: 1,
            perPage: 10,
            sortKey: '',
            numberOfGuests: 0,
            goingWithPets: undefined,
            where: '',
            countOnly: false,
        };

        mockedApi.post.mockResolvedValueOnce(mockResponseData);

        await getPropertyList(payload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_PROPERTY_LIST' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_PROPERTY, payload);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_PROPERTY_LIST',
            payload: {
                data: mockResponseData.data.data,
                meta: mockResponseData.data.meta,
                page: 1,
            },
        });
    });

    it('should dispatch property list with coordinates and guest details', async () => {
        const searchBarData = {
            guestCount: true,
            numberOfGuests: 3,
            numberOfChildren: 1,
            latitude: 12.34,
            longitude: 56.78,
            goingWithPets: true,
            isSearchClicked: true,
            activeTab: 'standard',
        };

        const payload = {
            page: 2,
            perPage: 10,
            sortKey: '',
            numberOfGuests: 3,
            numberOfChildren: 1,
            goingWithPets: true,
            latitude: 12.34,
            longitude: 56.78,
            where: '',
            countOnly: false,
        };

        mockedApi.post.mockResolvedValueOnce(mockResponseData);

        await getPropertyList(payload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_PROPERTY_LIST' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_PROPERTY, payload);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_PROPERTY_LIST',
            payload: {
                data: mockResponseData.data.data,
                meta: mockResponseData.data.meta,
                page: 2,
            },
        });
    });

    it('should merge filterData into payload when filter button clicked', async () => {
        const searchBarData = {
            isSearchClicked: false,
        };

        const filterData = {
            propertyType: 'Villa',
            bedCount: 3,
            minInternetSpeed: 100,
        };

        const payload = {
            page: 1,
            perPage: 10,
            sortKey: '',
            propertyType: 'Villa',
            bedCount: 3,
            minInternetSpeed: 100,
            countOnly: false,
        };

        mockedApi.post.mockResolvedValueOnce(mockResponseData);

        await getPropertyList(payload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_PROPERTY_LIST' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_PROPERTY, payload);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_PROPERTY_LIST',
            payload: {
                data: mockResponseData.data.data,
                meta: mockResponseData.data.meta,
                page: 1,
            },
        });
    });


    it('should dispatch with full payload and skip merging filterData when search clicked', async () => {
        const searchBarData = {
            guestCount: true,
            numberOfGuests: 4,
            numberOfChildren: 1,
            goingWithPets: true,
            latitude: 23.123,
            longitude: 72.456,
            where: '',
            countryName: ['USA'],
            activeTab: 'standard',
            checkIn: '2025-08-01',
            checkOut: '2025-08-10',
            isSearchClicked: true,
        };

        const sortKey = { slug: 'price-asc' };
        const currentPage = 2;

        const payload = {
            page: currentPage,
            perPage: 10,
            sortKey: sortKey.slug,
            numberOfGuests: 4,
            numberOfChildren: 1,
            goingWithPets: true,
            latitude: 23.123,
            longitude: 72.456,
            where: '',
            countryName: ['USA'],
            checkIn: '2025-08-01',
            checkOut: '2025-08-10',
            countOnly: false,
        };

        mockedApi.post.mockResolvedValueOnce(mockResponseData);

        await getPropertyList(payload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_PROPERTY_LIST' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_PROPERTY, payload);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_PROPERTY_LIST',
            payload: {
                data: mockResponseData.data.data,
                meta: mockResponseData.data.meta,
                page: currentPage,
            },
        });
    });

    it('should dispatch with full payload including filterData when filter button clicked', async () => {
        const searchBarData = {
            guestCount: true,
            numberOfGuests: 2,
            numberOfChildren: 0,
            goingWithPets: false,
            where: 'New York',
            countryName: ['USA'],
            activeTab: 'standard',
            checkIn: '2025-08-01',
            checkOut: '2025-08-10',
            isSearchClicked: false,
        };

        const filterData = {
            propertyType: 'Villa',
            priceStart: 200,
            priceEnd: 800,
            locationId: 'loc001',
            homebaseId: 'hb002',
            workspaceId: 'ws003',
            bedTypeId: 'bt004',
            smoking: false,
            adultsOnly: true,
            petFriendly: true,
            bedroomCount: 3,
            bathroomCount: 2,
            bedCount: 4,
            minInternetSpeed: 100,
        };

        const sortKey = { slug: 'latest' };
        const currentPage = 1;

        const payload = {
            page: currentPage,
            perPage: 10,
            sortKey: sortKey.slug,
            numberOfGuests: 2,
            numberOfChildren: 0,
            goingWithPets: false,
            where: 'New York',
            countryName: ['USA'],
            checkIn: '2025-08-01',
            checkOut: '2025-08-10',
            propertyType: 'Villa',
            priceStart: 200,
            priceEnd: 800,
            locationId: 'loc001',
            homebaseId: 'hb002',
            workspaceId: 'ws003',
            bedTypeId: 'bt004',
            smoking: false,
            adultsOnly: true,
            petFriendly: true,
            bedroomCount: 3,
            bathroomCount: 2,
            bedCount: 4,
            minInternetSpeed: 100,
            countOnly: false,
        };

        mockedApi.post.mockResolvedValueOnce(mockResponseData);

        await getPropertyList(payload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_PROPERTY_LIST' });
        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_PROPERTY, payload);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_PROPERTY_LIST',
            payload: {
                data: mockResponseData.data.data,
                meta: mockResponseData.data.meta,
                page: currentPage,
            },
        });
    });


});
