"use client";

import React from "react";
import { adminListUsers } from "@/lib/frontend/apiClient";
import { ADMIN_USERS_SORT } from "@/lib/frontend/admin/users/usersSorting";

function normalizeQuery(query) {
	const q =
		typeof query?.q === "string" && query.q.trim() ? query.q.trim() : null;

	const role =
		typeof query?.role === "string" && query.role.trim()
			? query.role.trim()
			: null;

	const branchId =
		typeof query?.branchId === "string" && query.branchId.trim()
			? query.branchId.trim()
			: null;

	const sort =
		typeof query?.sort === "string" && query.sort.trim()
			? query.sort.trim()
			: ADMIN_USERS_SORT.DEFAULT;

	return { q, role, branchId, sort };
}

function buildKey({ q, role, branchId, sort, limit }) {
	return `${q || ""}|${role || ""}|${branchId || ""}|${sort}|${String(limit)}`;
}

/**
 * useAdminUsersQuery
 *
 * - Loads first page on query changes.
 * - Supports cursor-based "load more".
 * - Includes race protection to avoid stale appends.
 */
export function useAdminUsersQuery({ query, limit = 50 }) {
	const normalized = React.useMemo(() => {
		return normalizeQuery(query);
	}, [query?.q, query?.role, query?.branchId]);

	const key = React.useMemo(() => {
		return buildKey({ ...normalized, limit });
	}, [normalized.q, normalized.role, normalized.branchId, normalized.sort, limit]);

	const [status, setStatus] = React.useState("loading"); // loading|success|error
	const [items, setItems] = React.useState([]);
	const [nextCursor, setNextCursor] = React.useState(null);
	const [error, setError] = React.useState(null);

	const [isLoadingMore, setIsLoadingMore] = React.useState(false);
	const [loadMoreError, setLoadMoreError] = React.useState(null);

	const [refreshTick, setRefreshTick] = React.useState(0);

	const keyRef = React.useRef(key);
	React.useEffect(() => {
		keyRef.current = key;
	}, [key]);

	const firstReqIdRef = React.useRef(0);
	const moreReqIdRef = React.useRef(0);

	const refresh = React.useCallback(() => {
		setRefreshTick((n) => n + 1);
	}, []);

	const runFirstPage = React.useCallback(async () => {
		const reqId = ++firstReqIdRef.current;

		setStatus("loading");
		setError(null);
		setItems([]);
		setNextCursor(null);

		// Reset load-more state on first page load
		setIsLoadingMore(false);
		setLoadMoreError(null);

		try {
			const res = await adminListUsers({
				q: normalized.q,
				role: normalized.role,
				branchId: normalized.branchId,
				sort: normalized.sort,
				limit,
				cursor: null,
			});

			if (reqId !== firstReqIdRef.current) return;

			const list = Array.isArray(res?.items) ? res.items : [];
			const next =
				typeof res?.nextCursor === "string" && res.nextCursor.trim()
					? res.nextCursor
					: null;

			setItems(list);
			setNextCursor(next);
			setStatus("success");
		} catch (err) {
			if (reqId !== firstReqIdRef.current) return;
			setError(err);
			setStatus("error");
		}
	}, [normalized.q, normalized.role, normalized.branchId, normalized.sort, limit]);

	React.useEffect(() => {
		runFirstPage();
	}, [runFirstPage, key, refreshTick]);

	const loadMore = React.useCallback(async () => {
		if (!nextCursor) return;
		if (isLoadingMore) return;

		const baseKey = keyRef.current;
		const reqId = ++moreReqIdRef.current;

		setIsLoadingMore(true);
		setLoadMoreError(null);

		try {
			const res = await adminListUsers({
				q: normalized.q,
				role: normalized.role,
				branchId: normalized.branchId,
				sort: normalized.sort,
				limit,
				cursor: nextCursor,
			});

			// Ignore stale
			if (reqId !== moreReqIdRef.current) return;
			if (keyRef.current !== baseKey) return;

			const more = Array.isArray(res?.items) ? res.items : [];
			const next =
				typeof res?.nextCursor === "string" && res.nextCursor.trim()
					? res.nextCursor
					: null;

			setItems((prev) => [...prev, ...more]);
			setNextCursor(next);
		} catch (err) {
			setLoadMoreError(err);
		} finally {
			if (reqId === moreReqIdRef.current) {
				setIsLoadingMore(false);
			}
		}
	}, [
		nextCursor,
		isLoadingMore,
		normalized.q,
		normalized.role,
		normalized.branchId,
		normalized.sort,
		limit,
	]);

	return {
		status,
		items,
		nextCursor,
		error,
		refresh,
		loadMore,
		isLoadingMore,
		loadMoreError,
	};
}
