const assert = require('assert');
const { mapFormula, getSafeCode, getTableFieldMap } = require('../utils/formula-compat');

const cases = [
    {
        name: '子表百分比公式应安全化并包裹为 amis 表达式',
        input: '{工程应预估支出(3)}/{合同金额(1)}*100',
        expected: '${工程应预估支出_3/合同金额_1*100}'
    },
    {
        name: '减法复合公式应安全化并包裹为 amis 表达式',
        input: '{工程应预估支出(3)}-{工程已预估支出(4)}-{当期甲方供料(5)}',
        expected: '${工程应预估支出_3-工程已预估支出_4-当期甲方供料_5}'
    },
    {
        name: '{now} 应转换为 NOW()',
        input: '{now}',
        expected: '${NOW()}'
    },
    {
        name: '对象字段语法应转为 __expand',
        input: '{合同}.name',
        expected: '${合同__expand.name}'
    },
    {
        name: '上下文字段 applicant 不应加 __expand',
        input: '{applicant}.name',
        expected: '${applicant.name}'
    },
    {
        name: '已是 amis 语法应返回 null',
        input: '${a + b}',
        expected: null
    }
];

// tableFieldMap 相关测试
const tableFieldMapCases = [
    {
        name: 'sum({子表字段}) 应转换为 ARRAYMAP 表达式',
        input: 'sum({出票金额})',
        tableFieldMap: { '出票金额': '表格' },
        expected: "${SUM(ARRAYMAP(表格, item => item['出票金额']))}"
    },
    {
        name: 'average({子表字段}) 应转换为 ARRAYMAP 表达式',
        input: 'average({出票金额})',
        tableFieldMap: { '出票金额': '表格' },
        expected: "${AVG(ARRAYMAP(表格, item => item['出票金额']))}"
    },
    {
        name: 'count({子表字段}) 应转换为 ARRAYMAP 表达式',
        input: 'count({出票金额})',
        tableFieldMap: { '出票金额': '表格' },
        expected: "${COUNT(ARRAYMAP(表格, item => item['出票金额']))}"
    },
    {
        name: 'max({子表字段}) 应转换为 ARRAYMAP 表达式',
        input: 'max({出票金额})',
        tableFieldMap: { '出票金额': '表格' },
        expected: "${MAX(ARRAYMAP(表格, item => item['出票金额']))}"
    },
    {
        name: 'min({子表字段}) 应转换为 ARRAYMAP 表达式',
        input: 'min({出票金额})',
        tableFieldMap: { '出票金额': '表格' },
        expected: "${MIN(ARRAYMAP(表格, item => item['出票金额']))}"
    },
    {
        name: 'numToRMB({子表字段}) 应转换为 ARRAYMAP 表达式',
        input: 'numToRMB({出票金额})',
        tableFieldMap: { '出票金额': '表格' },
        expected: "${UPPERMONEY(ARRAYMAP(表格, item => item['出票金额']))}"
    },
    {
        name: '非子表字段的 sum 不应生成 ARRAYMAP',
        input: 'sum({金额})',
        tableFieldMap: {},
        expected: '${SUM(金额)}'
    },
    {
        name: '无 tableFieldMap 时 sum 应保持原行为',
        input: 'sum({出票金额})',
        tableFieldMap: null,
        expected: '${SUM(出票金额)}'
    },
    {
        name: '子表字段名含特殊字符应安全化表格 code',
        input: 'sum({出票金额})',
        tableFieldMap: { '出票金额': '表格(1)' },
        expected: "${SUM(ARRAYMAP(表格_1, item => item['出票金额']))}"
    },
    // Bug 8: 全角括号 sum（{x}）
    {
        name: '全角括号聚合: sum（{金额（替换）}）子表字段',
        input: 'sum（{金额（替换）}）',
        tableFieldMap: { '金额（替换）': '表格' },
        expected: "${SUM(ARRAYMAP(表格, item => item['金额（替换）']))}"
    },
    {
        name: '全角括号聚合: sum（{amount}）非子表字段',
        input: 'sum（{amount}）',
        tableFieldMap: null,
        expected: '${SUM(amount)}'
    },
    // Bug 8: 缺失括号 sum{x}
    {
        name: '缺失括号: sum{含税金额} 子表字段',
        input: 'sum{含税金额}',
        tableFieldMap: { '含税金额': '明细' },
        expected: "${SUM(ARRAYMAP(明细, item => item['含税金额']))}"
    },
    {
        name: '缺失括号: sum{(金额)} 字段code为金额（内层括号应被清理）',
        input: 'sum{(金额)}',
        tableFieldMap: { '金额': '明细' },
        expected: "${SUM(ARRAYMAP(明细, item => item['金额']))}"
    },
    {
        name: '缺失括号: sum{(金额)} 字段code为(金额)（边界 case，预处理D会去掉内层括号，导致查不到 tableFieldMap）',
        input: 'sum{(金额)}',
        tableFieldMap: { '(金额)': '明细' },
        expected: '${SUM(金额)}'
    },
    {
        name: '缺失括号: sum{概算总价} 非子表字段',
        input: 'sum{概算总价}',
        tableFieldMap: null,
        expected: '${SUM(概算总价)}'
    },
    {
        name: '缺失括号: sum{项目预算金额} 子表字段',
        input: 'sum{项目预算金额}',
        tableFieldMap: { '项目预算金额': '费用明细' },
        expected: "${SUM(ARRAYMAP(费用明细, item => item['项目预算金额']))}"
    }
];

const run = () => {
    console.log('[formula-compat] running tests...');

    assert.strictEqual(getSafeCode('工程形象进度%(2)=(3)/(1)'), '工程形象进度__2__3__1');

    // 方括号转换测试
    assert.strictEqual(
        mapFormula('[{油量（本地）} + {油量（异地）}]/{本月里程数}*100'),
        '${(油量_本地 + 油量_异地)/本月里程数*100}',
        '方括号分组应转换为圆括号'
    );
    assert.strictEqual(
        mapFormula('{月末里程数} - {月初里程数}'),
        '${月末里程数 - 月初里程数}',
        '简单减法公式应正确转换'
    );

    for (const item of cases) {
        const actual = mapFormula(item.input);
        assert.strictEqual(
            actual,
            item.expected,
            `${item.name}\ninput: ${item.input}\nexpected: ${item.expected}\nactual: ${actual}`
        );
    }

    for (const item of tableFieldMapCases) {
        const actual = mapFormula(item.input, item.tableFieldMap);
        assert.strictEqual(
            actual,
            item.expected,
            `${item.name}\ninput: ${item.input}\ntableFieldMap: ${JSON.stringify(item.tableFieldMap)}\nexpected: ${item.expected}\nactual: ${actual}`
        );
    }

    // getTableFieldMap 测试
    const fields = [
        { type: 'text', code: '标题' },
        { type: 'table', code: '表格', fields: [
            { code: '出票金额', type: 'number' },
            { code: '到期日', type: 'date' }
        ]},
        { type: 'section', code: '分组', fields: [
            { type: 'table', code: '明细表', fields: [
                { code: '数量', type: 'number' }
            ]}
        ]}
    ];
    const map = getTableFieldMap(fields);
    assert.strictEqual(map['出票金额'], '表格', 'getTableFieldMap 应映射子表字段到父表');
    assert.strictEqual(map['到期日'], '表格', 'getTableFieldMap 应映射子表字段到父表');
    assert.strictEqual(map['数量'], '明细表', 'getTableFieldMap 应递归处理 section 中的 table');
    assert.strictEqual(map['标题'], undefined, 'getTableFieldMap 非子表字段不应在映射中');

    const totalAssertions = 1 + 2 + cases.length + tableFieldMapCases.length + 4;
    console.log(`[formula-compat] ${totalAssertions} assertions passed.`);
};

if (require.main === module) {
    run();
}

module.exports = {
    run
};
