import { React } from '@gravityforms/libraries';
import { getModules } from './utils';

const { useEffect, useState } = React;

/**
 * @function getOrganizedData
 * @description Get the organized data for the data grid.
 *
 * @since 5.1.0
 *
 * @param {object}  params                  The parameters to get the organized data.
 * @param {Array}   params.data             The data to organize.
 * @param {number}  params.dataPerPage      The number of data per page.
 * @param {Array}   params.modules          The modules to use in the data grid.
 * @param {object}  params.moduleAttributes The module attributes.
 * @param {object}  params.moduleState      The module state.
 * @param {boolean} params.useAjax          Whether to use AJAX to load data.
 *
 * @return {Array} The organized data.
 */
export const getOrganizedData = ( {
	data = [],
	dataPerPage = 20,
	modules = [],
	moduleAttributes = {},
	moduleState = {},
	useAjax = false,
} ) => {
	if ( useAjax ) {
		return data;
	}

	let sortedData = [ ...data ];
	const { ColumnSort } = getModules( modules, [ 'ColumnSort' ] );
	const { currentPage = 0 } = moduleState;

	if ( ColumnSort ) {
		const { sortFunction } = moduleAttributes?.columnSort || {};
		const { sortBy, sortOrder } = moduleState;
		sortedData = ColumnSort.getSortedData( {
			data: sortedData,
			sortFunction,
			sortBy,
			sortOrder,
		} );
	}

	return sortedData.slice( currentPage * dataPerPage, ( currentPage + 1 ) * dataPerPage );
};

/**
 * @module useDataGridState
 * @description A hook to manage the state of a data grid.
 *
 * @since 5.1.0
 *
 * @param {object}  params                  The parameters for the hook.
 * @param {Array}   params.data             The data to display in the data grid.
 * @param {number}  params.dataPerPage      The number of items to display per page.
 * @param {object}  params.initialState     The initial state of the data grid.
 * @param {Array}   params.modules          The modules to use in the data grid.
 * @param {object}  params.moduleAttributes The module attributes.
 * @param {boolean} params.useAjax          Whether to use AJAX to load data.
 *
 * @return {object} The data grid state and actions.
 */
const useDataGridState = ( {
	data = [],
	dataPerPage = 20,
	initialState = {},
	modules = [],
	moduleAttributes = {},
	useAjax = false,
} ) => {
	const [ isLoading, setIsLoading ] = useState( initialState?.isLoading || false );
	const [ gridLocked, setGridLocked ] = useState( initialState?.gridLocked || false );
	const [ moduleState, setModuleState ] = useState( () => {
		const {
			BulkActions,
			GridPagination,
			Search,
			SimpleFilters,
			DateFilters,
			ColumnSort,
		} = getModules(
			modules,
			[
				'BulkActions',
				'GridPagination',
				'Search',
				'SimpleFilters',
				'DateFilters',
				'ColumnSort',
			],
		);

		return {
			...( ( BulkActions && BulkActions?.getDefaultState() ) || {} ),
			...( ( GridPagination && GridPagination?.getDefaultState() ) || {} ),
			...( ( Search && Search?.getDefaultState() ) || {} ),
			...( ( SimpleFilters && SimpleFilters?.getDefaultState() ) || {} ),
			...( ( DateFilters && DateFilters?.getDefaultState() ) || {} ),
			...( ( ColumnSort && ColumnSort?.getDefaultState() ) || {} ),
			...initialState?.moduleState || {},
		};
	} );
	const [ organizedData, setOrganizedData ] = useState( () => getOrganizedData( {
		data,
		dataPerPage,
		useAjax,
		modules,
		moduleAttributes,
		moduleState,
	} ) );

	const updateModuleState = ( newState ) => {
		setModuleState( { ...moduleState, ...newState } );
	};

	useEffect( () => {
		setGridLocked( organizedData.length === 0 || isLoading );
	}, [ organizedData, isLoading ] );

	useEffect( () => {
		if ( useAjax ) {
			return;
		}

		setOrganizedData( getOrganizedData( {
			data,
			dataPerPage,
			modules,
			moduleAttributes,
			moduleState,
			useAjax,
		} ) );
	}, [
		dataPerPage,
		data,
		moduleState,
		useAjax,
	] );

	return {
		moduleState,
		updateModuleState,
		isLoading,
		setIsLoading,
		gridLocked,
		setGridLocked,
		organizedData,
		setOrganizedData,
	};
};

export default useDataGridState;
