import $i18n from '../../../../../../../locales/i18n.js';
/**
 * 公式计算引擎
 * 使用 expr-eval 进行安全的表达式解析，映射函数调用到 @formulajs/formulajs
 * 函数列表与 cn-next-smart FORMULA_FUNC_LIST 保持对齐（仅包含 formulajs 支持的函数）
 */
import { Parser } from 'expr-eval';
import * as formulajs from '@formulajs/formulajs';
import { ALLOWED_FORMULAJS_FUNCTIONS, FORMULA_ERROR } from './formula-constants';
import { extractCellTextValue } from '../../../../../../../cn-ai-table/view/components/views/table-view/cell-format/text-extractors';
const FIELD_REF_REGEX = /\{([^}]+)\}/g;
/**
 * 从公式表达式中提取引用的字段 dataIndex 列表
 */
export function extractReferencedFields(expression) {
    const fields = [];
    let match;
    const regex = new RegExp(FIELD_REF_REGEX.source, 'g');
    while ((match = regex.exec(expression)) !== null) {
        if (!fields.includes(match[1])) {
            fields.push(match[1]);
        }
    }
    return fields;
}
/**
 * 从行数据中提取字段的真实值（与 AI 字段取值逻辑一致）。
 * 优先通过 extractCellTextValue 获取格式化显示值，无列定义时回退到原始值。
 */
function resolveFieldValue(fieldName, row, context) {
    const { columnDefinitions, processedColumnMap, rowIndex = 0 } = context || {};
    // processedColumnMap 仅承载 cell 函数；列的 format 注册表在 extractCellTextValue 内部
    // 已能独立按 column.format 取到 label，因此 processedColumnMap 真正可选——
    // 只要有 columnDefinitions 就能进入格式化提取分支，没有 processedColumn 也不会崩溃。
    if (columnDefinitions) {
        const column = columnDefinitions.find((col) => col.dataIndex === fieldName);
        if (column) {
            const processedColumn = processedColumnMap === null || processedColumnMap === void 0 ? void 0 : processedColumnMap.get(fieldName);
            const result = extractCellTextValue(row[fieldName], column, row, processedColumn, undefined, rowIndex);
            const text = result.text;
            if (text === undefined || text === null || text === '') {
                return '0';
            }
            const num = Number(text);
            if (!isNaN(num) && text.trim() !== '') {
                return String(num);
            }
            return JSON.stringify(text);
        }
    }
    const value = row[fieldName];
    if (value === undefined || value === null || value === '') {
        return '0';
    }
    if (typeof value === 'string') {
        const num = Number(value);
        if (!isNaN(num) && value.trim() !== '') {
            return String(num);
        }
        return JSON.stringify(value);
    }
    return String(value);
}
/**
 * 将公式中的字段引用 {dataIndex} 替换为行数据中的实际值
 */
function substituteFieldRefs(expression, row, context) {
    return expression.replace(FIELD_REF_REGEX, (_match, fieldName) => {
        return resolveFieldValue(fieldName, row, context);
    });
}
/**
 * 从 formulajs 导出的函数集合中获取安全映射
 */
function getFormulajsFunctionMap() {
    const fnMap = {};
    const fjsModule = formulajs;
    ALLOWED_FORMULAJS_FUNCTIONS.forEach((name) => {
        if (typeof fjsModule[name] === 'function') {
            fnMap[name] = fjsModule[name];
        }
    });
    return fnMap;
}
const formulajsFnMap = getFormulajsFunctionMap();
/**
 * 检测公式中使用的函数是否都在白名单中
 */
export function validateFormula(expression) {
    const funcCallRegex = /([A-Z_][A-Z0-9_]*)\s*\(/gi;
    let match;
    const regex = new RegExp(funcCallRegex.source, 'gi');
    while ((match = regex.exec(expression)) !== null) {
        const funcName = match[1].toUpperCase();
        if (!ALLOWED_FORMULAJS_FUNCTIONS.has(funcName)) {
            return {
                valid: false,
                error: $i18n.get({
                    id: 'UnsupportedFunctionMatch',
                    dm: '不支持的函数: {match}',
                }, { match: match[1] }),
            };
        }
    }
    return { valid: true };
}
/**
 * 评估单个公式表达式，返回计算结果
 */
export function evaluateFormula(expression, context) {
    var _a, _b;
    if (!expression || expression.trim() === '') {
        return '';
    }
    let expr = expression.trim();
    if (expr.startsWith('=')) {
        expr = expr.substring(1).trim();
    }
    const refFields = extractReferencedFields(expr);
    for (const field of refFields) {
        if (context.row[field] === undefined) {
            return FORMULA_ERROR.REF;
        }
    }
    const validation = validateFormula(expr);
    if (!validation.valid) {
        return FORMULA_ERROR.NAME;
    }
    try {
        const substituted = substituteFieldRefs(expr, context.row, context);
        return evaluateWithFormulajs(substituted);
    }
    catch (e) {
        if (((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.includes('Division by zero')) || ((_b = e === null || e === void 0 ? void 0 : e.message) === null || _b === void 0 ? void 0 : _b.includes('divide by zero'))) {
            return FORMULA_ERROR.DIV0;
        }
        return FORMULA_ERROR.ERROR;
    }
}
/**
 * 使用 formulajs 函数和 expr-eval 进行安全求值
 */
function evaluateWithFormulajs(expression) {
    const funcCallRegex = /([A-Z_][A-Z0-9_]*)\s*\(([^()]*(?:\([^()]*\)[^()]*)*)\)/i;
    let expr = expression;
    let maxIterations = 50;
    while (funcCallRegex.test(expr) && maxIterations > 0) {
        maxIterations--;
        expr = expr.replace(funcCallRegex, (_match, funcName, argsStr) => {
            const upperName = funcName.toUpperCase();
            const fn = formulajsFnMap[upperName];
            if (!fn) {
                throw new Error(`Unsupported function: ${funcName}`);
            }
            const args = parseArguments(argsStr);
            const evaluatedArgs = args.map((arg) => {
                const trimmed = arg.trim();
                if (trimmed === '')
                    return 0;
                if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
                    return trimmed.slice(1, -1);
                }
                if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
                    return trimmed.slice(1, -1);
                }
                try {
                    return evaluateSimpleExpression(trimmed);
                }
                catch {
                    return trimmed;
                }
            });
            const result = fn(...evaluatedArgs);
            if (typeof result === 'string') {
                return JSON.stringify(result);
            }
            return String(result);
        });
    }
    return evaluateSimpleExpression(expr);
}
/**
 * 解析函数参数（处理嵌套括号和字符串中的逗号）
 */
function parseArguments(argsStr) {
    const args = [];
    let current = '';
    let depth = 0;
    let inString = false;
    let stringChar = '';
    for (let i = 0; i < argsStr.length; i++) {
        const char = argsStr[i];
        if (inString) {
            current += char;
            if (char === stringChar && argsStr[i - 1] !== '\\') {
                inString = false;
            }
            continue;
        }
        if (char === '"' || char === "'") {
            inString = true;
            stringChar = char;
            current += char;
            continue;
        }
        if (char === '(') {
            depth++;
            current += char;
        }
        else if (char === ')') {
            depth--;
            current += char;
        }
        else if (char === ',' && depth === 0) {
            args.push(current.trim());
            current = '';
        }
        else {
            current += char;
        }
    }
    if (current.trim()) {
        args.push(current.trim());
    }
    return args;
}
/**
 * 使用 expr-eval 安全地计算简单算术表达式
 */
function evaluateSimpleExpression(expr) {
    const trimmed = expr.trim();
    if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
        return trimmed.slice(1, -1);
    }
    const num = Number(trimmed);
    if (!isNaN(num) && trimmed !== '') {
        return num;
    }
    if (trimmed.toLowerCase() === 'true')
        return true;
    if (trimmed.toLowerCase() === 'false')
        return false;
    try {
        const parser = new Parser();
        const parsed = parser.parse(trimmed);
        return parsed.evaluate({});
    }
    catch {
        return trimmed;
    }
}
/**
 * 批量计算公式列的所有行
 */
export function computeFormulaColumn(expression, rows, fields, columnDataIndex, columnDefinitions, processedColumnMap) {
    const allowedFunctions = ALLOWED_FORMULAJS_FUNCTIONS;
    return rows.map((row, rowIndex) => {
        const context = {
            row,
            fields,
            allowedFunctions,
            columnDefinitions,
            processedColumnMap,
            rowIndex,
        };
        const result = evaluateFormula(expression, context);
        return {
            ...row,
            [columnDataIndex]: result,
        };
    });
}
/**
 * 批量重算所有公式列
 */
export function computeAllFormulaColumns(formulaConfigs, rows, fields, columnDefinitions, processedColumnMap) {
    let result = rows;
    const configs = Object.values(formulaConfigs);
    for (const config of configs) {
        result = computeFormulaColumn(config.expression, result, fields, config.columnCode, columnDefinitions, processedColumnMap);
    }
    return result;
}
