/**
 * Copyright IBM Corp. 2020, 2026
 *
 * This source code is licensed under the Apache-2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

const require_runtime = require("../../../../../../_virtual/_rolldown/runtime.js");
const require_usePreviousValue = require("../../../../../../global/js/hooks/usePreviousValue.js");
const require_uuidv4 = require("../../../../../../global/js/utils/uuidv4.js");
const require_constants = require("../constants.js");
const require_FilterProvider = require("../FilterProvider.js");
const require_handleCheckboxChange = require("../handleCheckboxChange.js");
const require_OverflowCheckboxes = require("../OverflowCheckboxes.js");
const require_utils = require("../utils.js");
let react = require("react");
react = require_runtime.__toESM(react);
let _carbon_react = require("@carbon/react");
//#region src/components/Datagrid/Datagrid/addons/Filtering/hooks/useFilters.jsx
/**
* Copyright IBM Corp. 2023, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
const emptyArray = [];
const useFilters = ({ updateMethod, filters = emptyArray, setAllFilters, variation, reactTableFiltersState, onCancel, panelOpen, autoHideFilters, isFetching }) => {
	const { state, tableId: contextTableId } = (0, react.useContext)(require_FilterProvider.FilterContext);
	const { savedFilters } = state;
	/** State */
	const [filtersState, setFiltersState] = (0, react.useState)(require_utils.getInitialStateFromFilters(filters, variation, reactTableFiltersState));
	const [fetchingReset, setFetchingReset] = (0, react.useState)(false);
	const [filtersObjectArray, setFiltersObjectArray] = (0, react.useState)(reactTableFiltersState);
	const previousState = require_usePreviousValue.usePreviousValue({ panelOpen });
	const filteredItemsRef = (0, react.useRef)(void 0);
	const prevFiltersRef = (0, react.useRef)(JSON.stringify(filtersState));
	const lastAppliedFilters = (0, react.useRef)(JSON.stringify(reactTableFiltersState));
	const prevFiltersObjectArrayRef = (0, react.useRef)(JSON.stringify(filtersObjectArray));
	const holdingPrevFiltersRef = (0, react.useRef)(void 0);
	const holdingLastAppliedFiltersRef = (0, react.useRef)([]);
	const holdingPrevFiltersObjectArrayRef = (0, react.useRef)([]);
	/** Methods */
	const revertToPreviousFilters = (0, react.useCallback)(() => {
		setFiltersState(JSON.parse(prevFiltersRef.current));
		setFiltersObjectArray(JSON.parse(prevFiltersObjectArrayRef.current));
		setAllFilters(JSON.parse(lastAppliedFilters.current));
		holdingPrevFiltersRef.current = JSON.parse(prevFiltersRef.current);
		holdingLastAppliedFiltersRef.current = JSON.parse(prevFiltersObjectArrayRef.current);
		holdingPrevFiltersObjectArrayRef.current = JSON.parse(lastAppliedFilters.current);
	}, [setAllFilters]);
	const reset = (0, react.useCallback)((tableId) => {
		if (tableId === contextTableId) {
			const initialFiltersState = require_utils.getInitialStateFromFilters(filters, variation, []);
			const initialFiltersObjectArray = [];
			setFiltersState(initialFiltersState);
			setFiltersObjectArray(initialFiltersObjectArray);
			setAllFilters([]);
			prevFiltersRef.current = JSON.stringify(initialFiltersState);
			prevFiltersObjectArrayRef.current = JSON.stringify(initialFiltersObjectArray);
			lastAppliedFilters.current = JSON.stringify([]);
		}
	}, [
		filters,
		setAllFilters,
		variation,
		contextTableId
	]);
	const applyFilters = ({ column, value, type }) => {
		if (type === "date" && value.length > 0 && !value[1]) return;
		const filterCopy = [...filtersObjectArray];
		const filter = filterCopy.find((item) => item.id === column);
		if (filter) filter.value = value;
		else filterCopy.push({
			id: column,
			value,
			type
		});
		const index = filterCopy.findIndex(({ id }) => id === column);
		const clearCheckbox = (type === "checkbox" || type === "multiSelect") && filterCopy[index].value.every(({ selected }) => selected === false);
		const clearDate = type === "date" && value.length === 0;
		if (clearCheckbox || clearDate || (type === "dropdown" || type === "radio") && value === "Any" || type === "number" && value === "") filterCopy.splice(index, 1);
		setFiltersObjectArray(filterCopy);
		if (updateMethod === "instant") setAllFilters(filterCopy);
	};
	/** Render the individual filter component */
	const renderFilter = ({ type, column, props: components }) => {
		let filter;
		const isPanel = variation === require_constants.PANEL;
		if (!type) return console.error(`type: ${type}; does not exist as a type of filter.`);
		const renderCheckboxes = () => {
			if (variation === "panel" && filtersState[column].value.length > 10 && !autoHideFilters) return /* @__PURE__ */ react.default.createElement(require_OverflowCheckboxes.default, {
				components,
				type,
				column,
				setFiltersState,
				filtersState,
				applyFilters
			});
			return /* @__PURE__ */ react.default.createElement(_carbon_react.FormGroup, components.FormGroup, filtersState[column].value.map((option) => /* @__PURE__ */ react.default.createElement(_carbon_react.Checkbox, {
				key: option.id,
				...option,
				onChange: (_, { checked }) => {
					require_handleCheckboxChange.handleCheckboxChange({
						checked,
						filtersState,
						column,
						option,
						setFiltersState,
						applyFilters,
						type
					});
				},
				checked: option.selected
			})));
		};
		switch (type) {
			case require_constants.DATE:
				filter = /* @__PURE__ */ react.default.createElement(_carbon_react.DatePicker, {
					...components.DatePicker,
					onChange: (value) => {
						setFiltersState({
							...filtersState,
							[column]: {
								value,
								type
							}
						});
						applyFilters({
							column,
							value,
							type
						});
						components.DatePicker.onChange?.(value);
					},
					value: filtersState[column].value,
					datePickerType: "range"
				}, /* @__PURE__ */ react.default.createElement(_carbon_react.DatePickerInput, {
					placeholder: "mm/dd/yyyy",
					labelText: "Start date",
					...components.DatePickerInput.start
				}), /* @__PURE__ */ react.default.createElement(_carbon_react.DatePickerInput, {
					placeholder: "mm/dd/yyyy",
					labelText: "End date",
					...components.DatePickerInput.end
				}));
				break;
			case require_constants.NUMBER:
				filter = /* @__PURE__ */ react.default.createElement(_carbon_react.NumberInput, {
					step: 1,
					allowEmpty: true,
					hideSteppers: true,
					...components.NumberInput,
					onChange: (event) => {
						setFiltersState({
							...filtersState,
							[column]: {
								value: event.target.value,
								type
							}
						});
						applyFilters({
							column,
							value: event.target.value,
							type
						});
						components.NumberInput.onChange?.(event);
					},
					value: filtersState[column].value
				});
				break;
			case require_constants.CHECKBOX:
				filter = renderCheckboxes();
				break;
			case require_constants.RADIO:
				{
					const { name } = { ...components.RadioButtonGroup };
					filter = /* @__PURE__ */ react.default.createElement(_carbon_react.FormGroup, components.FormGroup, /* @__PURE__ */ react.default.createElement(_carbon_react.RadioButtonGroup, {
						...components.RadioButtonGroup,
						valueSelected: filtersState[column]?.value === "" ? components.DefaultRadioButton?.value ?? "Any" : filtersState[column]?.value,
						onChange: (selected) => {
							setFiltersState({
								...filtersState,
								[column]: {
									value: selected,
									type
								}
							});
							applyFilters({
								column,
								value: selected,
								type
							});
							components.RadioButtonGroup.onChange?.(selected);
						}
					}, /* @__PURE__ */ react.default.createElement(_carbon_react.RadioButton, {
						id: components?.DefaultRadioButton?.id ?? `any__${name}`,
						labelText: components?.DefaultRadioButton?.labelText ?? "Any",
						value: components?.DefaultRadioButton?.value ?? "Any",
						...components.DefaultRadioButton
					}), components.RadioButton.map((radio) => /* @__PURE__ */ react.default.createElement(_carbon_react.RadioButton, {
						key: radio.id ?? radio.labelText ?? radio.value,
						...radio
					}))));
				}
				break;
			case require_constants.DROPDOWN:
				filter = /* @__PURE__ */ react.default.createElement(_carbon_react.Dropdown, {
					...components.Dropdown,
					selectedItem: filtersState[column]?.value === "" ? "Any" : filtersState[column]?.value,
					items: ["Any", ...components.Dropdown.items],
					onChange: ({ selectedItem }) => {
						setFiltersState({
							...filtersState,
							[column]: {
								value: selectedItem,
								type
							}
						});
						applyFilters({
							column,
							value: selectedItem,
							type
						});
						components.Dropdown.onChange?.(selectedItem);
					}
				});
				break;
			case require_constants.MULTISELECT: {
				const isStringArray = components.MultiSelect.items.length && typeof components.MultiSelect.items[0] === "string";
				const selectedFilters = Array.isArray(filtersState[column]?.value) ? filtersState[column].value.filter((i) => i.selected) : [];
				const filteredItems = components.MultiSelect.items.map((item) => {
					if (selectedFilters.filter((a) => isStringArray ? a.id === item : a.id === item.id).length) return item;
					return null;
				}).filter(Boolean);
				const isEqual = compareFilterItems(filteredItems);
				if (!isEqual) filteredItemsRef.current = [...filteredItems];
				const getKey = () => {
					return isEqual ? { key: require_uuidv4.default() } : column;
				};
				filter = /* @__PURE__ */ react.default.createElement(_carbon_react.MultiSelect, {
					...components.MultiSelect,
					selectedItems: filteredItems,
					key: getKey(),
					onChange: ({ selectedItems }) => {
						const allOptions = filtersState[column].value;
						const foundItems = selectedItems.map((item) => {
							if (allOptions.filter((option) => isStringArray ? option.id === item : option.id === item.id)) return allOptions.filter((option) => isStringArray ? option.id === item : option.id === item.id)[0];
							return null;
						}).filter(Boolean);
						filteredItemsRef.current = [...foundItems];
						allOptions.map((a) => a.selected = false);
						foundItems.map((item) => {
							const foundOriginalItem = allOptions.filter((a) => isStringArray ? a === item : a.id === item.id);
							if (foundOriginalItem && foundOriginalItem.length) foundOriginalItem[0].selected = true;
						});
						if (!selectedItems.length) allOptions.map((a) => a.selected = false);
						setFiltersState({
							...filtersState,
							[column]: {
								value: allOptions,
								type
							}
						});
						applyFilters({
							column,
							value: [...filtersState[column].value],
							type
						});
						components.MultiSelect?.onChange?.(selectedItems);
					}
				});
				break;
			}
		}
		if (isPanel) return /* @__PURE__ */ react.default.createElement(_carbon_react.Layer, { key: column }, filter);
		return /* @__PURE__ */ react.default.createElement(react.default.Fragment, { key: column }, filter);
	};
	const compareFilterItems = (filteredItems) => {
		const filteredItemsId = filteredItems.map((item) => item.id) ?? [];
		const previousFilteredItemsId = filteredItemsRef?.current?.map((item) => item.id) ?? [];
		const set1 = new Set(filteredItemsId);
		const set2 = new Set(previousFilteredItemsId);
		if (set1.size !== set2.size) return false;
		return [...set1].every((element) => set2.has(element));
	};
	/** This useEffect will properly handle the previous filters when the panel closes
	* 1. If the panel closes we need to call the reset fn but also store the
	* previous filters in a (new) temporary place.
	* 2. When the panel opens again, take the values from the temporary place
	* and populate the filter state with them
	*/
	(0, react.useEffect)(() => {
		if (!panelOpen && previousState?.panelOpen) {
			revertToPreviousFilters();
			setAllFilters(holdingLastAppliedFiltersRef.current);
		}
		if (panelOpen && !previousState?.panelOpen) {
			if (holdingPrevFiltersRef.current && holdingLastAppliedFiltersRef.current && holdingPrevFiltersObjectArrayRef.current) {
				setFiltersState(holdingPrevFiltersRef.current);
				setFiltersObjectArray(holdingLastAppliedFiltersRef.current);
				setAllFilters(JSON.parse(prevFiltersObjectArrayRef.current));
			}
		}
	}, [
		panelOpen,
		previousState,
		previousState?.panelOpen,
		reset,
		setAllFilters,
		revertToPreviousFilters
	]);
	(0, react.useEffect)(() => {
		if (isFetching && !fetchingReset) {
			setFiltersState(JSON.parse(prevFiltersRef.current));
			setFiltersObjectArray(JSON.parse(prevFiltersRef.current));
			setAllFilters(JSON.parse(prevFiltersObjectArrayRef.current));
			setFetchingReset(true);
		}
		if (isFetching && fetchingReset) {
			const cleanFilters = (originalFilterState) => {
				const copy = { ...originalFilterState };
				return savedFilters.map((f) => {
					if (Object.hasOwn(copy, f.id)) {
						copy[f.id] = f;
						return copy;
					}
					return copy;
				})[0];
			};
			if (savedFilters && savedFilters.length) {
				setFiltersObjectArray(savedFilters);
				setFiltersState(cleanFilters(filtersState) ?? []);
			}
		}
		if (!isFetching) setFetchingReset(false);
	}, [
		isFetching,
		reactTableFiltersState,
		setAllFilters,
		fetchingReset,
		savedFilters,
		filtersObjectArray
	]);
	(0, react.useEffect)(function reflectLastAppliedFiltersWhenReactTableUpdates() {
		lastAppliedFilters.current = JSON.stringify(reactTableFiltersState);
	}, [reactTableFiltersState, lastAppliedFilters]);
	const cancel = () => {
		if (updateMethod === "batch") {
			revertToPreviousFilters();
			onCancel();
		}
	};
	/** The purpose of this function is to sync any changes in react-tables state.filters array and reflect
	those new filter changes in the panel/flyout state. The external change is triggered if setAllFilters is called outside of the Datagrid */
	(0, react.useEffect)(function updateStateAndFiltersToReflectExternalFilterChanges() {
		const newFiltersState = require_utils.getInitialStateFromFilters(filters, variation, reactTableFiltersState);
		setFiltersState(newFiltersState);
		prevFiltersRef.current = JSON.stringify(newFiltersState);
		prevFiltersObjectArrayRef.current = JSON.stringify(reactTableFiltersState);
		setFiltersObjectArray(reactTableFiltersState);
	}, [
		filters,
		reactTableFiltersState,
		variation
	]);
	return {
		filtersState,
		setFiltersState,
		prevFiltersObjectArrayRef,
		prevFiltersRef,
		revertToPreviousFilters,
		reset,
		renderFilter,
		filtersObjectArray,
		lastAppliedFilters,
		cancel
	};
};
//#endregion
exports.default = useFilters;
