import React from 'react';
import { DEFAULT_POLLING_INTERVAL, DEFAULT_POLLING_MAX_COUNT, DEFAULT_POLLING_TIMEOUT_TEXT, ERROR_QUERY_TEXT, } from '../types/constants';
/**
 * 轮询 Hook
 *
 * 封装 adapter.query 的定时轮询逻辑，支持：
 * - 可配置间隔与最大次数
 * - requestToken 竞态保护
 * - 组件卸载安全（isMountedRef）
 */
export function useChatPolling({ adapter, pollingConfig, onEvent }) {
    var _a, _b, _c;
    const interval = (_a = pollingConfig === null || pollingConfig === void 0 ? void 0 : pollingConfig.interval) !== null && _a !== void 0 ? _a : DEFAULT_POLLING_INTERVAL;
    const maxCount = (_b = pollingConfig === null || pollingConfig === void 0 ? void 0 : pollingConfig.maxCount) !== null && _b !== void 0 ? _b : DEFAULT_POLLING_MAX_COUNT;
    const timeoutText = (_c = pollingConfig === null || pollingConfig === void 0 ? void 0 : pollingConfig.timeoutText) !== null && _c !== void 0 ? _c : DEFAULT_POLLING_TIMEOUT_TEXT;
    const timerRef = React.useRef(null);
    const countRef = React.useRef(0);
    const isMountedRef = React.useRef(true);
    const activeTokenRef = React.useRef(0);
    React.useEffect(() => {
        isMountedRef.current = true;
        return () => {
            isMountedRef.current = false;
            if (timerRef.current) {
                clearTimeout(timerRef.current);
                timerRef.current = null;
            }
        };
    }, []);
    const stopPolling = React.useCallback(() => {
        if (timerRef.current) {
            clearTimeout(timerRef.current);
            timerRef.current = null;
        }
        countRef.current = 0;
        activeTokenRef.current = 0;
    }, []);
    const startPolling = React.useCallback((params) => {
        const { conversationId, messageId, placeholderMessageId, setMessages, onDone, requestToken } = params;
        activeTokenRef.current = requestToken;
        countRef.current = 0;
        const poll = async () => {
            var _a;
            if (!isMountedRef.current || activeTokenRef.current !== requestToken)
                return;
            countRef.current += 1;
            const count = countRef.current;
            onEvent === null || onEvent === void 0 ? void 0 : onEvent({ name: 'poll_tick', payload: { count, conversationId, messageId } });
            if (count > maxCount) {
                onEvent === null || onEvent === void 0 ? void 0 : onEvent({ name: 'poll_timeout', payload: { count, conversationId } });
                setMessages((prev) => updatePlaceholder(prev, placeholderMessageId, timeoutText, 'error'));
                onDone();
                return;
            }
            try {
                const res = await adapter.query({ conversationId, messageId });
                if (!isMountedRef.current || activeTokenRef.current !== requestToken)
                    return;
                const newText = (_a = res.text) !== null && _a !== void 0 ? _a : '';
                setMessages((prev) => {
                    var _a;
                    const idx = prev.findIndex((m) => m.id === placeholderMessageId);
                    if (idx < 0)
                        return prev;
                    const hasNewText = newText.trim() !== '';
                    const contentToSet = hasNewText ? newText : prev[idx].content;
                    const status = res.onGoing ? 'generating' : 'done';
                    const mergedMeta = res.meta ? { ...prev[idx].meta, ...res.meta } : prev[idx].meta;
                    const updated = [...prev];
                    updated[idx] = { ...updated[idx], content: contentToSet, status, meta: mergedMeta };
                    if (!res.onGoing && ((_a = res.quickReplies) === null || _a === void 0 ? void 0 : _a.length)) {
                        updated[idx] = { ...updated[idx], quickReplies: res.quickReplies };
                    }
                    return updated;
                });
                if (res.onGoing) {
                    timerRef.current = setTimeout(poll, interval);
                }
                else {
                    timerRef.current = null;
                    onDone();
                }
            }
            catch {
                timerRef.current = null;
                if (isMountedRef.current && activeTokenRef.current === requestToken) {
                    setMessages((prev) => updatePlaceholder(prev, placeholderMessageId, ERROR_QUERY_TEXT, 'error'));
                    onEvent === null || onEvent === void 0 ? void 0 : onEvent({ name: 'error', payload: { phase: 'polling', conversationId } });
                    onDone();
                }
            }
        };
        poll();
    }, [adapter, interval, maxCount, timeoutText, onEvent]);
    return { startPolling, stopPolling, activeTokenRef };
}
function updatePlaceholder(messages, placeholderId, content, status) {
    const idx = messages.findIndex((m) => m.id === placeholderId);
    if (idx < 0)
        return messages;
    const updated = [...messages];
    updated[idx] = { ...updated[idx], content, status };
    return updated;
}
