import { apiMutate } from "../../../utilities/useAxiosMutate.mjs";
import { Box as Box$1 } from "../../Box.mjs";
import { FluentSelectMenu } from "./FluentSelectMenu.mjs";
import React, { Children, forwardRef, useCallback, useEffect, useRef, useState } from "react";
import { CircularProgress } from "@material-ui/core";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
import { makeStyles as makeStyles$1 } from "@material-ui/core/styles";
import Alert from "@material-ui/lab/Alert";
//#region src/UI/inputs/menus/FluentScrollLoadAutocompleteMenu.jsx
const useStyles = makeStyles$1((theme) => ({
	listbox: {
		position: "relative",
		maxHeight: 300,
		overflow: "auto"
	},
	listboxHidden: { overflow: "hidden" },
	loadingItem: {
		textAlign: "center",
		padding: theme.spacing(1)
	},
	overlay: {
		position: "absolute",
		inset: 0,
		background: "rgba(255,255,255,.95)",
		display: "flex",
		flexDirection: "column",
		alignItems: "center",
		justifyContent: "center",
		zIndex: 1
	},
	overlayText: { marginTop: theme.spacing(1) },
	alert: { marginTop: theme.spacing(1) }
}));
/**
* **FluentScrollLoadAutocompleteMenu**
*
* A drop‑in extension for MUI’s `<Autocomplete>` that:
*
* 1. Fetches paginated / sortable data from any REST endpoint  
* 2. Implements infinite scrolling with automatic scroll‑position restore  
* 3. Supports client‑side filtering, grouping   
* 4. Displays a Material UI `<CircularProgress>` while loading and a MUI `<Alert>` on errors
*
* Internally it wraps **unity‑fluent‑library**’s `<FluentSelectMenu>` so you get the same
* keyboard navigation and styling as the rest of the Fluent controls.
*
* ---
*
* ### Typical usage
* ```jsx
* const endpoint = (q, page, size, sortCol, sortDir) =>
*   `/api/products?search=${q}&page=${page}&pageSize=${size}&sort=${sortCol}&dir=${sortDir}`;
*
* const map = (raw) => ({
*   items: raw.items,
*   total: raw.totalRows,
* });
*
* <FluentScrollLoadAutocompleteMenu
*   apiBaseUrl="https://api.example.com"
*   apiEndpoint={endpoint}
*   mapResponse={map}
*   onChange={(product) => console.log(product)}
* />
* ```
* ---
*
* @param {Object}   props
* @param {string}   props.apiBaseUrl   Base URL forwarded to **apiMutate**
* @param {Function} props.apiEndpoint  `(keyword, page, pageSize, sortCol, sortDir) => string`
* @param {Function} props.mapResponse  Maps raw API payload → `{ items, total }`
* @param {Function} [props.onChange]   Fires when the user selects/clears an option
* @param {Function} [props.getOptionLabel] Returns the display label for an item (default: `o.name`)
* @param {Function} [props.groupBy]    Returns a group heading string for an item
* @param {string}   [props.placeholder='Search…'] Placeholder text
* @param {string}   [props.displayProperty='name'] Property passed to `<FluentSelectMenu>`
* @param {number|string} [props.width=300] Fixed width of the component container
* @param {boolean}  [props.fetchEnabled=true] Disable to work fully offline
* @param {*}        [props.initialValue=null]  Pre‑selected value shown immediately
* @param {Array}    [props.initialOptions=[]]  Pre‑loaded options shown immediately
* @param {boolean}  [props.isPaginated=true]   Disable if your API returns the full list
* @param {boolean}  [props.isSortable=true]    Disable server‑side sorting
* @param {boolean}  [props.isFilterable=true]  Disable server‑side filtering
* @param {number}   [props.pageSize=50]        Items per page when paginating
* @param {string}   [props.sortColumn='Name']  Default sort column
* @param {'ASC'|'DESC'} [props.sortDirection='ASC'] Default sort direction
*
* @returns {JSX.Element}
*/
const FluentScrollLoadAutocompleteMenu = ({ apiBaseUrl, apiEndpoint, apiConfig = {}, apiData = null, mapResponse, onChange, getOptionLabel = (o) => o?.name ?? "", groupBy, placeholder = "Search…", displayProperty = "name", width = 300, fetchEnabled = true, initialValue = null, initialOptions = [], isPaginated = true, isSortable = true, isFilterable = true, pageSize = 50, sortColumn = "Name", sortDirection = "ASC" }) => {
	const classes = useStyles();
	const [options, setOptions] = useState(initialOptions);
	const [value, setValue] = useState(initialValue);
	const [inputValue, setInputValue] = useState("");
	const [loading, setLoading] = useState(false);
	const [loadingMore, setLoadingMore] = useState(false);
	const [error, setError] = useState(null);
	const [pageNumber, setPageNumber] = useState(1);
	const [totalRows, setTotalRows] = useState(0);
	const configRef = useRef(apiConfig);
	const dataRef = useRef(apiData);
	const listboxRef = useRef(null);
	const prevScrollPositionRef = useRef(0);
	const { t } = useTranslation();
	/**
	* Fetches a page of data from the provided API endpoint and updates the component state accordingly.
	*
	* This function supports:
	* - Filtering (if `isFilterable` is true)
	* - Sorting (if `isSortable` is true)
	* - Pagination (based on the `page` and `pageSize` arguments)
	* - Infinite scroll appending (via the `append` flag)
	*
	* @function fetchPage
	* @param {string} keyword - The keyword to filter results by (if filtering is enabled)
	* @param {number} page - The page number to fetch
	* @param {boolean} [append=false] - If true, appends results to the current list; otherwise replaces it
	* @returns {Promise<void>} - Resolves once data is fetched and state is updated
	*/
	const fetchPage = useCallback(async (keyword, page, append = false) => {
		if (!fetchEnabled) return;
		setError(null);
		page === 1 ? setLoading(true) : setLoadingMore(true);
		try {
			const { items, total } = mapResponse((await apiMutate(apiBaseUrl, apiEndpoint(isFilterable ? keyword : "", page, pageSize, isSortable ? sortColumn : "", isSortable ? sortDirection : "ASC"), configRef.current, dataRef.current)).data);
			setOptions((prev) => append ? [...prev, ...items] : items);
			setTotalRows(total);
			setPageNumber(page);
		} catch (err) {
			setError(err.response?.data?.message ?? err.message ?? t("Unknown error"));
		} finally {
			page === 1 ? setLoading(false) : setLoadingMore(false);
		}
	}, [
		apiBaseUrl,
		apiEndpoint,
		mapResponse,
		pageSize,
		sortColumn,
		sortDirection,
		isFilterable,
		isSortable,
		fetchEnabled,
		t
	]);
	const handleListboxScroll = (e) => {
		if (!isPaginated) return;
		const node = e.currentTarget;
		prevScrollPositionRef.current = node.scrollTop;
		if (node.scrollTop + node.clientHeight >= node.scrollHeight - 30 && !loadingMore && options.length < totalRows) fetchPage(inputValue, pageNumber + 1, true);
	};
	/**
	* **Listbox**
	*
	* Custom scrollable container used by the Autocomplete dropdown.
	* - Attaches a ref to preserve scroll position between pages.
	* - Displays a loading message if no options are present initially.
	* - Shows a full overlay spinner when `loadingMore` is true.
	*
	* This component is passed as the `ListboxComponent` to FluentSelectMenu’s
	* Autocomplete integration, enabling infinite scroll with visual feedback.
	*
	* @param {Object} props
	* @param {React.ReactNode} props.children - Option elements to render
	* @param {boolean} props.initialLoading - Whether to show the “Loading…” message initially
	* @param {React.Ref} ref - Forwarded ref from the Autocomplete dropdown
	* @returns {JSX.Element}
	*/
	const Listbox = forwardRef(({ children, initialLoading, ...other }, ref) => /* @__PURE__ */ React.createElement("ul", {
		ref: (inst) => {
			if (inst) listboxRef.current = inst;
			if (typeof ref === "function") ref(inst);
			else if (ref) ref.current = inst;
		},
		...other,
		style: {
			position: "relative",
			maxHeight: 300,
			overflow: loadingMore ? "hidden" : "auto"
		}
	}, Children.count(children) === 0 && initialLoading ? /* @__PURE__ */ React.createElement("li", { style: {
		textAlign: "center",
		padding: 8
	} }, t("Loading...")) : children, loadingMore && /* @__PURE__ */ React.createElement(Box$1, { className: classes.overlay }, /* @__PURE__ */ React.createElement(CircularProgress, { size: 20 }), /* @__PURE__ */ React.createElement("span", { className: classes.overlayText }, t("Loading...")))));
	Listbox.displayName = "FluentSMAutocompleteListbox";
	useEffect(() => {
		if (!fetchEnabled || !isFilterable) return;
		if (value && inputValue === getOptionLabel(value)) return;
		const timer = setTimeout(() => fetchPage(inputValue, 1, false), 400);
		return () => clearTimeout(timer);
	}, [
		inputValue,
		fetchPage,
		value,
		getOptionLabel,
		isFilterable,
		fetchEnabled
	]);
	useEffect(() => {
		if (!fetchEnabled || isFilterable) return;
		fetchPage("", 1, false);
	}, [
		isFilterable,
		fetchEnabled,
		fetchPage
	]);
	useEffect(() => {
		if (!loadingMore && listboxRef.current) listboxRef.current.scrollTop = prevScrollPositionRef.current;
	}, [options, loadingMore]);
	useEffect(() => {
		configRef.current = apiConfig;
	}, [apiConfig]);
	useEffect(() => {
		dataRef.current = apiData;
	}, [apiData]);
	return /* @__PURE__ */ React.createElement(Box$1, { width }, /* @__PURE__ */ React.createElement(FluentSelectMenu, {
		placeholder,
		data: options,
		displayProperty,
		onChange: (val) => {
			setValue(val);
			onChange?.(val);
		},
		InputProps: { endAdornment: loading && pageNumber === 1 ? /* @__PURE__ */ React.createElement(CircularProgress, {
			color: "inherit",
			size: 20
		}) : null },
		autoCompleteProps: {
			value,
			inputValue,
			onInputChange: (_e, v) => setInputValue(v),
			loading: loading && pageNumber === 1,
			getOptionLabel,
			groupBy,
			ListboxComponent: Listbox,
			ListboxProps: {
				onScroll: handleListboxScroll,
				initialLoading: loading && pageNumber === 1
			}
		}
	}), error && /* @__PURE__ */ React.createElement(Alert, {
		severity: "error",
		style: { marginTop: 8 }
	}, error));
};
FluentScrollLoadAutocompleteMenu.propTypes = {
	apiBaseUrl: PropTypes.string.isRequired,
	apiEndpoint: PropTypes.func.isRequired,
	apiConfig: PropTypes.object,
	apiData: PropTypes.any,
	mapResponse: PropTypes.func.isRequired,
	onChange: PropTypes.func,
	getOptionLabel: PropTypes.func,
	groupBy: PropTypes.func,
	placeholder: PropTypes.string,
	displayProperty: PropTypes.string,
	width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
	fetchEnabled: PropTypes.bool,
	initialValue: PropTypes.any,
	initialOptions: PropTypes.array,
	isPaginated: PropTypes.bool,
	isSortable: PropTypes.bool,
	isFilterable: PropTypes.bool,
	pageSize: PropTypes.number,
	sortColumn: PropTypes.string,
	sortDirection: PropTypes.oneOf(["ASC", "DESC"])
};
//#endregion
export { FluentScrollLoadAutocompleteMenu };

//# sourceMappingURL=FluentScrollLoadAutocompleteMenu.mjs.map