import React, { useCallback, useMemo, useRef, useState } from 'react';
import { TAB, TAB_NAME } from '../../../constant';
import { apiFetch } from '../../../../../lib/fetch/apiClient';
export function useNotificationData({ limit }) {
    const [listData, setListData] = useState([]);
    const [count, setCount] = useState({ all: 0, to_me: 0, system: 0 });
    const [activeTab, setActiveTab] = useState(TAB.ALL);
    const [page, setPage] = useState(1);
    const [hasMore, setHasMore] = useState(true);
    const [loadingInit, setLoadingInit] = useState(false);
    const [loadingMore, setLoadingMore] = useState(false);
    // Refs for mutable loading state — avoids stale closure in fetchData deps
    const loadingInitRef = useRef(false);
    const loadingMoreRef = useRef(false);
    // Generation counter: fresh fetches (append=false) always increment this.
    // Any in-flight request whose gen doesn't match current gen is discarded.
    const genRef = useRef(0);
    const tabs = useMemo(() => [
        {
            name: (React.createElement("span", { className: 'flex items-center gap-1' },
                React.createElement("span", null, TAB_NAME[TAB.ALL]),
                (count === null || count === void 0 ? void 0 : count.all) > 0 && (React.createElement("span", { className: 'shadow-sm min-w-4 rounded-md bg-red-500 p-1 text-center text-[10px] font-semibold leading-none text-white' }, (count === null || count === void 0 ? void 0 : count.all) > 99 ? '99+' : count === null || count === void 0 ? void 0 : count.all)))),
            value: TAB.ALL,
            count: '',
        },
        {
            name: (React.createElement("span", { className: 'flex items-center gap-1' },
                React.createElement("span", null, TAB_NAME[TAB.TO_ME]),
                (count === null || count === void 0 ? void 0 : count.to_me) > 0 && (React.createElement("span", { className: 'shadow-sm min-w-4 rounded-md bg-red-500 p-1 text-center text-[10px] font-semibold leading-none text-white' }, (count === null || count === void 0 ? void 0 : count.to_me) > 99 ? '99+' : count === null || count === void 0 ? void 0 : count.to_me)))),
            value: TAB.TO_ME,
            count: '',
        },
        {
            name: (React.createElement("span", { className: 'flex items-center gap-1' },
                React.createElement("span", null, TAB_NAME[TAB.SYSTEM]),
                (count === null || count === void 0 ? void 0 : count.system) > 0 && (React.createElement("span", { className: 'shadow-sm min-w-4 rounded-md bg-red-500 p-1 text-center text-[10px] font-semibold leading-none text-white' }, (count === null || count === void 0 ? void 0 : count.system) > 99 ? '99+' : count === null || count === void 0 ? void 0 : count.system)))),
            value: TAB.SYSTEM,
            count: '',
        },
    ], [count === null || count === void 0 ? void 0 : count.all, count === null || count === void 0 ? void 0 : count.system, count === null || count === void 0 ? void 0 : count.to_me]);
    const mergeUniqueById = useCallback((prev, items) => {
        const seen = new Set(prev.map((x) => x.id));
        const merged = [...prev];
        for (const it of items) {
            if ((it === null || it === void 0 ? void 0 : it.id) && !seen.has(it.id)) {
                merged.push(it);
                seen.add(it.id);
            }
        }
        return merged;
    }, []);
    const fetchData = useCallback(async (tabValue, pageValue, append, onSettled) => {
        var _a, _b;
        if (append) {
            // load-more: skip if any fetch is already in-flight
            if (loadingInitRef.current || loadingMoreRef.current)
                return;
        }
        // Fresh fetch always supersedes previous; load-more takes the current gen
        // so that a subsequent fresh fetch can invalidate it mid-flight.
        const myGen = append ? genRef.current : ++genRef.current;
        if (append) {
            loadingMoreRef.current = true;
            setLoadingMore(true);
        }
        else {
            // Cancel any in-flight load-more from the previous page
            loadingMoreRef.current = false;
            setLoadingMore(false);
            loadingInitRef.current = true;
            setLoadingInit(true);
        }
        try {
            const data = (await apiFetch('/inapp-noti/notification', {
                method: 'GET',
                params: { tab: tabValue, page: pageValue, limit },
            }));
            // Discard results from a superseded request
            if (genRef.current !== myGen)
                return;
            const items = (_a = data === null || data === void 0 ? void 0 : data.items) !== null && _a !== void 0 ? _a : [];
            setCount((_b = data === null || data === void 0 ? void 0 : data.counts) !== null && _b !== void 0 ? _b : { all: 0, to_me: 0, system: 0 });
            setListData((prev) => {
                if (!append)
                    return items;
                return mergeUniqueById(prev, items);
            });
            setHasMore(items.length === limit);
            setPage(pageValue);
        }
        catch (error) {
            if (genRef.current !== myGen)
                return;
            console.error('Error fetching notifications:', error);
        }
        finally {
            if (genRef.current === myGen) {
                if (append) {
                    loadingMoreRef.current = false;
                    setLoadingMore(false);
                }
                else {
                    loadingInitRef.current = false;
                    setLoadingInit(false);
                    // Only the current-gen fresh fetch notifies the caller.
                    // Stale fetches are blocked by the gen check above, so this
                    // callback is never invoked for superseded requests.
                    onSettled === null || onSettled === void 0 ? void 0 : onSettled();
                }
            }
        }
    }, [limit, mergeUniqueById]);
    const resetList = useCallback(() => {
        setListData([]);
        setPage(1);
        setHasMore(true);
    }, []);
    const loadMore = useCallback(async () => {
        if (loadingInitRef.current || loadingMoreRef.current)
            return;
        if (!hasMore)
            return;
        await fetchData(activeTab, page + 1, true);
    }, [activeTab, page, hasMore, fetchData]);
    return {
        // state
        listData,
        count,
        tabs,
        activeTab,
        setActiveTab,
        page,
        hasMore,
        loadingInit,
        loadingMore,
        // actions
        fetchFirstPage: (tab, onSettled) => fetchData(tab, 1, false, onSettled),
        loadMore,
        resetList,
    };
}
//# sourceMappingURL=useNotificationData.js.map