import $i18n from '../../../../locales/i18n.js'; // 第三方依赖
import isFunction from 'lodash/isFunction';
// ==================== 常量配置 ====================
// API 最大 pageSize 限制
export const MAX_API_PAGE_SIZE = 100;
// 批次分组大小（每5个批次为一组并发请求）
export const BATCH_GROUP_SIZE = 5;
// 批次请求重试配置
export const BATCH_RETRY_CONFIG = {
    maxRetries: 3, // 最大重试次数
    timeoutMs: 30000, // 超时时间（30秒）
};
// ==================== 批次请求辅助函数 ====================
/**
 * 计算需要分批次请求的批次页码范围 [startBatch, endBatch]
 * 例如：每页 1000、第 2 页 → 需要第 11～20 批（每批 100 条）
 * 若传入 totalCount，则按有效行下标截断，避免总条数不足时仍发满「逻辑页」对应的批次数
 */
export function calculateBatchRange(userPageSize, userCurrentPage, totalCount) {
    if (userPageSize <= MAX_API_PAGE_SIZE) {
        return [userCurrentPage, userCurrentPage];
    }
    const startIndex = (userCurrentPage - 1) * userPageSize;
    const endIndex = startIndex + userPageSize - 1;
    let effectiveEndIndex = endIndex;
    if (totalCount != null && totalCount >= 0) {
        if (startIndex >= totalCount) {
            return [1, 0];
        }
        effectiveEndIndex = Math.min(endIndex, totalCount - 1);
    }
    const startBatch = Math.floor(startIndex / MAX_API_PAGE_SIZE) + 1;
    const endBatch = Math.floor(effectiveEndIndex / MAX_API_PAGE_SIZE) + 1;
    return [startBatch, endBatch];
}
/**
 * 创建批次分组（每5个一批）
 * 组与组串行执行，组内并发请求
 */
export function createBatchGroups(startBatch, endBatch) {
    const batchPages = [];
    for (let batchPage = startBatch; batchPage <= endBatch; batchPage++) {
        batchPages.push(batchPage);
    }
    const groups = [];
    for (let i = 0; i < batchPages.length; i += BATCH_GROUP_SIZE) {
        groups.push(batchPages.slice(i, i + BATCH_GROUP_SIZE));
    }
    return groups;
}
/**
 * 带超时的 Promise
 */
function withTimeout(promise, timeoutMs) {
    return Promise.race([
        promise,
        new Promise((_, reject) => setTimeout(() => reject(new Error($i18n.get({
            id: 'RequestTimeoutTimeoutMsms',
            dm: '请求超时 ({timeoutMs}ms)',
        }, { timeoutMs }))), timeoutMs)),
    ]);
}
/**
 * 带重试的批次请求
 * 每次请求超时后重试，最多重试 maxRetries 次
 */
function fetchSingleBatchWithRetry(batchPage, fetchSingleBatch, maxRetries, timeoutMs) {
    let retryCount = 0;
    const attemptFetch = () => {
        const fetchPromise = fetchSingleBatch(batchPage);
        return withTimeout(fetchPromise, timeoutMs).catch((error) => {
            retryCount++;
            // eslint-disable-next-line no-console
            console.warn(`[batch-request] 批次 ${batchPage} 请求失败 (第 ${retryCount} 次尝试):`, {
                error: (error === null || error === void 0 ? void 0 : error.message) || error,
                retryCount,
                maxRetries,
            });
            if (retryCount < maxRetries) {
                return attemptFetch();
            }
            // eslint-disable-next-line no-console
            console.error(`[batch-request] 批次 ${batchPage} 达到重试上限，放弃请求:`, {
                error: (error === null || error === void 0 ? void 0 : error.message) || error,
                retryCount,
                maxRetries,
            });
            throw error;
        });
    };
    return attemptFetch()
        .then((data) => ({
        success: true,
        data,
        batchPage,
    }))
        .catch((error) => ({
        success: false,
        error: error instanceof Error ? error : new Error(String(error)),
        batchPage,
    }));
}
/**
 * 处理一组批次请求的结果
 */
function processBatchGroupResults(settledResults, group) {
    const successResponses = [];
    const failedBatches = [];
    settledResults.forEach((result, index) => {
        const batchPage = group[index];
        if (result.status === 'fulfilled') {
            if (result.value.success) {
                successResponses.push(result.value.data);
            }
            else {
                const failedResult = result.value;
                failedBatches.push({
                    batchPage: failedResult.batchPage,
                    error: failedResult.error,
                });
                // eslint-disable-next-line no-console
                console.error(`[batch-request] 批次 ${batchPage} 最终失败:`, failedResult.error.message);
            }
        }
        else {
            const error = result.reason instanceof Error ? result.reason : new Error(String(result.reason));
            failedBatches.push({ batchPage, error });
            // eslint-disable-next-line no-console
            console.error(`[batch-request] 批次 ${batchPage} Promise rejected:`, result.reason);
        }
    });
    return { successResponses, failedBatches };
}
/**
 * 执行一组批次请求
 */
function executeBatchGroup(group, groupIndex, totalGroups, fetchSingleBatch) {
    const groupPromises = group.map((batchPage) => fetchSingleBatchWithRetry(batchPage, fetchSingleBatch, BATCH_RETRY_CONFIG.maxRetries, BATCH_RETRY_CONFIG.timeoutMs));
    return Promise.allSettled(groupPromises).then((settledResults) => {
        const { successResponses, failedBatches } = processBatchGroupResults(settledResults, group);
        return { successResponses, failedBatches };
    });
}
/**
 * 转换批次响应数据,得到表格层需要的结构，再交给 mergeBatchResponses 合并
 */
function transformBatchResponses(responses, responseTransform) {
    const transformedPromises = responses.map((res) => Promise.resolve(responseTransform((res === null || res === void 0 ? void 0 : res.data) || res, res)));
    return Promise.all(transformedPromises);
}
// ==================== 主函数 ====================
/**
 * 执行分批次请求（主函数）
 */
export function executeBatchRequests(params, options) {
    const { userPageSize, userCurrentPage, clearDataType, totalCount } = params;
    const { fetchSingleBatch, responseTransform, mergeBatchResponses, callback, errorHandler, onFinally, setLoading, releaseLock, } = options;
    // 保存 userCurrentPage，确保在 Promise 链中能访问到正确的值
    const savedUserCurrentPage = userCurrentPage;
    // 计算批次范围（totalCount 有值时与接口总条数对齐，减少无效批次）
    const [startBatch, endBatch] = calculateBatchRange(userPageSize, userCurrentPage, totalCount);
    // 创建批次分组
    const batchGroups = createBatchGroups(startBatch, endBatch);
    // 按组顺序执行，每组内部并发
    const allResponses = [];
    const failedBatches = [];
    let groupPromise = Promise.resolve();
    for (let groupIndex = 0; groupIndex < batchGroups.length; groupIndex++) {
        const group = batchGroups[groupIndex];
        groupPromise = groupPromise.then(() => executeBatchGroup(group, groupIndex + 1, batchGroups.length, fetchSingleBatch).then(({ successResponses, failedBatches: groupFailedBatches }) => {
            allResponses.push(...successResponses);
            failedBatches.push(...groupFailedBatches);
        }));
    }
    return groupPromise
        .then(() => {
        if (failedBatches.length > 0) {
            // eslint-disable-next-line no-console
            console.warn(`[batch-request] 分批次请求中有 ${failedBatches.length} 个批次失败:`, {
                failedBatches: failedBatches.map((f) => ({
                    batchPage: f.batchPage,
                    error: f.error.message,
                })),
                successCount: allResponses.length,
                totalCount: allResponses.length + failedBatches.length,
            });
        }
        return transformBatchResponses(allResponses, responseTransform).then((transformedResponses) => {
            const mergedResult = mergeBatchResponses(transformedResponses, userPageSize, savedUserCurrentPage);
            setLoading(false);
            releaseLock();
            callback && isFunction(callback) && callback(mergedResult, clearDataType);
            return mergedResult;
        });
    })
        .catch(errorHandler)
        .finally(() => {
        onFinally && onFinally();
    });
}
