/**
 *  @author: Hemal
 * File: getBlogList.test.ts
 * Purpose: This file contains unit tests for the `getBlogList` asynchronous thunk action.
 * Description:
 * - Utilizes `jest.mock` to mock the `apiClient` module.
 * - Tests the behavior of the `getBlogList` 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('getBlogList thunk', () => {
    const mockDispatch = jest.fn();

    /**
     * Asynchronous thunk action to fetch the blog list from the API.
     * Dispatches different Redux actions based on the API response.
     * 
     * @param payload - The data required for fetching the blog list, including pagination and search parameters.
     * @param callback - Optional callback function that receives the API response data.
     * 
     * Dispatches:
     * - REQUEST_BLOG_LIST: Before the API call to indicate loading.
     * - RESPONSE_BLOG_BANNER_LIST: If no search parameter is provided, dispatches the blog banner list response.
     * - SUCCESS_BLOG_LIST: On successful API response with the blog list data.
     * - FAILURE_BLOG_LIST: On API error.
     */


    const getBlogList = (payload: { page: number; perPage: number; search?: string }, callback?: (data: any) => void) => async (dispatch: any) => {
        try {
            dispatch({ type: 'REQUEST_BLOG_LIST' });

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

            if (callback) {
                callback(response?.data);
            }

            if (!payload.search) {
                dispatch({ type: 'RESPONSE_BLOG_BANNER_LIST', payload: response?.data });
            }

            dispatch({ type: 'SUCCESS_BLOG_LIST', payload: response?.data });
        } catch (error: any) {
            dispatch({ type: 'FAILURE_BLOG_LIST' });
        }
    };

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

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

    // Test cases when search is not provided
    it('should dispatch all success actions and invoke callback (no search)', async () => {
        mockedApi.post.mockResolvedValueOnce({ data: mockResponseData });

        const payload = { page: 1, perPage: 10, search: '' };
        const callback = jest.fn();

        await getBlogList(payload, callback)(mockDispatch);

        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_BLOG, payload);
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_BLOG_LIST' });
        expect(callback).toHaveBeenCalledWith(mockResponseData);
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'RESPONSE_BLOG_BANNER_LIST',
            payload: mockResponseData,
        });
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_BLOG_LIST',
            payload: mockResponseData,
        });
    });

    // Test cases when search is provided
    it('should dispatch success actions and skip banner list (with search)', async () => {
        mockedApi.post.mockResolvedValueOnce({ data: mockResponseData });

        const payload = { page: 1, perPage: 10, search: 'Test Property' };

        await getBlogList(payload)(mockDispatch);

        expect(mockedApi.post).toHaveBeenCalledWith(API_ENDPOINTS.LIST_BLOG, payload);
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_BLOG_LIST' });
        expect(mockDispatch).not.toHaveBeenCalledWith(expect.objectContaining({ type: 'RESPONSE_BLOG_BANNER_LIST' }));
        expect(mockDispatch).toHaveBeenCalledWith({
            type: 'SUCCESS_BLOG_LIST',
            payload: mockResponseData,
        });
    });

    // Test cases when API call fails
    it('should dispatch failure action on error', async () => {
        mockedApi.post.mockRejectedValueOnce(new Error('API failed'));

        const payload = { page: 1, perPage: 10, search: '' };

        await getBlogList(payload)(mockDispatch);

        expect(mockDispatch).toHaveBeenCalledWith({ type: 'REQUEST_BLOG_LIST' });
        expect(mockDispatch).toHaveBeenCalledWith({ type: 'FAILURE_BLOG_LIST' });
    });
});
