import $i18n from '../../../../../../../locales/i18n.js';
import { armsHottagLog } from '../../../../../../../utils/arms/arms-hot-tag-log.js';
/**
 * 公式字段配置面板
 * 交互流程：内联面板（字段名 + 编辑公式按钮）→ 点击"编辑公式"弹出 CnDialog
 */
import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import { CnButton, CnIcon, CnInput, CnDialog } from '@cainiaofe/cn-ui';
import { useModel } from '../../../../../../../utils/mobx-react-simpler/index.js';
import { FormulaEditor } from './formula-editor';
import { extractReferencedFields, validateFormula, evaluateFormula } from './formula-engine';
import { FORMULA_FIELD_WHITELIST_COMPONENTS } from '../constants/field-types';
import { FORMULA_FUNCTIONS, FORMULA_FUNCTION_CATEGORIES, FUNCTION_GROUP_LABELS, } from './formula-constants';
import { FieldReferenceItem, FunctionReferenceItem, InfoDetailPanel, } from './formula-panel-components';
import './formula-field-config-panel.scss';
export function FormulaFieldConfigPanel({ fieldLabel, columnCode: existingColumnCode, initialExpression, onSave, onCancel, }) {
    const dataModel = useModel('dataModel');
    const [fieldName, setFieldName] = useState(fieldLabel);
    const [expression, setExpression] = useState(initialExpression || '');
    const [validationError, setValidationError] = useState('');
    const [editorDialogVisible, setEditorDialogVisible] = useState(false);
    const [pendingExpression, setPendingExpression] = useState('');
    const [hoveredItem, setHoveredItem] = useState(null);
    const editorRef = useRef(null);
    const fieldNameInputRef = useRef(null);
    const hoverLeaveTimerRef = useRef(null);
    const getAvailableFields = useCallback(() => {
        const columnDefinitions = (dataModel === null || dataModel === void 0 ? void 0 : dataModel.columnDefinitions) || [];
        const fieldMap = (dataModel === null || dataModel === void 0 ? void 0 : dataModel.fieldMap) || {};
        return columnDefinitions
            .filter((col) => {
            if (col.isAiColumn)
                return false;
            if (col.format === 'formula')
                return false;
            const fieldInfo = fieldMap[col.dataIndex];
            const componentType = (fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo.component) || (fieldInfo === null || fieldInfo === void 0 ? void 0 : fieldInfo['x-component']);
            if (!componentType)
                return true;
            return FORMULA_FIELD_WHITELIST_COMPONENTS.includes(componentType);
        })
            .map((col) => {
            var _a;
            return ({
                dataIndex: col.dataIndex,
                title: col.title || col.dataIndex,
                component: (_a = fieldMap[col.dataIndex]) === null || _a === void 0 ? void 0 : _a.component,
            });
        });
    }, [dataModel]);
    const availableFields = useMemo(() => getAvailableFields(), [getAvailableFields]);
    const groupedFunctions = useMemo(() => {
        return FORMULA_FUNCTION_CATEGORIES.map((cat) => {
            var _a, _b, _c, _d;
            return ({
                category: cat,
                label: (_b = (_a = FUNCTION_GROUP_LABELS[cat]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : cat,
                i18nId: (_d = (_c = FUNCTION_GROUP_LABELS[cat]) === null || _c === void 0 ? void 0 : _c.i18nId) !== null && _d !== void 0 ? _d : cat,
                functions: FORMULA_FUNCTIONS.filter((fn) => fn.category === cat),
            });
        }).filter((g) => g.functions.length > 0);
    }, []);
    const previewResult = useMemo(() => {
        if (!pendingExpression.trim())
            return null;
        const rows = (dataModel === null || dataModel === void 0 ? void 0 : dataModel.rawData) || [];
        if (rows.length === 0)
            return null;
        try {
            const columnDefinitions = (dataModel === null || dataModel === void 0 ? void 0 : dataModel.columnDefinitions) || [];
            const processedColumnMap = (dataModel === null || dataModel === void 0 ? void 0 : dataModel.processedColumnMap) || new Map();
            const result = evaluateFormula(pendingExpression, {
                row: rows[0],
                fields: availableFields,
                allowedFunctions: new Set(FORMULA_FUNCTIONS.map((f) => f.name)),
                columnDefinitions,
                processedColumnMap,
                rowIndex: 0,
            });
            return result !== undefined && result !== null ? String(result) : null;
        }
        catch {
            return null;
        }
    }, [
        pendingExpression,
        dataModel === null || dataModel === void 0 ? void 0 : dataModel.rawData,
        dataModel === null || dataModel === void 0 ? void 0 : dataModel.columnDefinitions,
        dataModel === null || dataModel === void 0 ? void 0 : dataModel.processedColumnMap,
        availableFields,
    ]);
    useEffect(() => {
        const timer = setTimeout(() => {
            var _a, _b;
            if (fieldNameInputRef.current) {
                const inputNode = ((_b = (_a = fieldNameInputRef.current).getInputNode) === null || _b === void 0 ? void 0 : _b.call(_a)) || fieldNameInputRef.current;
                if (inputNode && typeof inputNode.focus === 'function') {
                    inputNode.focus();
                    if (typeof inputNode.select === 'function') {
                        inputNode.select();
                    }
                }
            }
        }, 100);
        return () => clearTimeout(timer);
    }, []);
    useEffect(() => {
        return () => {
            if (hoverLeaveTimerRef.current) {
                clearTimeout(hoverLeaveTimerRef.current);
            }
        };
    }, []);
    const handleExpressionChange = useCallback((newValue) => {
        setPendingExpression(newValue);
        if (validationError) {
            setValidationError('');
        }
    }, [validationError]);
    const handleHoverEnter = useCallback((item) => {
        if (hoverLeaveTimerRef.current) {
            clearTimeout(hoverLeaveTimerRef.current);
            hoverLeaveTimerRef.current = null;
        }
        setHoveredItem(item);
    }, []);
    const handleHoverLeave = useCallback(() => {
        hoverLeaveTimerRef.current = setTimeout(() => {
            setHoveredItem(null);
            hoverLeaveTimerRef.current = null;
        }, 150);
    }, []);
    const handleInfoPanelMouseEnter = useCallback(() => {
        if (hoverLeaveTimerRef.current) {
            clearTimeout(hoverLeaveTimerRef.current);
            hoverLeaveTimerRef.current = null;
        }
    }, []);
    const handleInfoPanelMouseLeave = useCallback(() => {
        setHoveredItem(null);
    }, []);
    const handleOpenEditorDialog = () => {
        var _a;
        armsHottagLog({
            hottag: 'cn-ai-table.formulaField.openEditor',
            name: $i18n.get({ id: 'OpenTheFormulaEditor', dm: '打开公式编辑器' }),
            c6: existingColumnCode || '',
            c7: String((_a = dataModel === null || dataModel === void 0 ? void 0 : dataModel.tableId) !== null && _a !== void 0 ? _a : ''),
        });
        setPendingExpression(expression);
        setHoveredItem(null);
        setEditorDialogVisible(true);
    };
    const handleEditorDialogConfirm = () => {
        var _a, _b;
        armsHottagLog({
            hottag: 'cn-ai-table.formulaField.editorConfirm',
            name: $i18n.get({ id: 'ConfirmFormulaEditing', dm: '确认公式编辑' }),
            c6: existingColumnCode || '',
            c7: String((_a = dataModel === null || dataModel === void 0 ? void 0 : dataModel.tableId) !== null && _a !== void 0 ? _a : ''),
            c8: String((_b = pendingExpression === null || pendingExpression === void 0 ? void 0 : pendingExpression.length) !== null && _b !== void 0 ? _b : 0),
        });
        setExpression(pendingExpression);
        setEditorDialogVisible(false);
    };
    const handleEditorDialogClose = () => {
        var _a;
        armsHottagLog({
            hottag: 'cn-ai-table.formulaField.editorCancel',
            name: $i18n.get({ id: 'CancelFormulaEditing', dm: '取消公式编辑' }),
            c6: existingColumnCode || '',
            c7: String((_a = dataModel === null || dataModel === void 0 ? void 0 : dataModel.tableId) !== null && _a !== void 0 ? _a : ''),
        });
        setPendingExpression('');
        setEditorDialogVisible(false);
    };
    const handleInsertFunction = (fn) => {
        const editor = editorRef.current;
        if (!editor)
            return;
        editor.insertText(`${fn.name}(`);
    };
    const validateForm = () => {
        if (!fieldName.trim()) {
            setValidationError($i18n.get({ id: 'PleaseEnterAFieldName', dm: '请输入字段名称' }));
            return false;
        }
        if (!expression.trim()) {
            setValidationError($i18n.get({ id: 'EnterFormula', dm: '请输入公式' }));
            return false;
        }
        const validation = validateFormula(expression);
        if (!validation.valid) {
            setValidationError(validation.error || '');
            return false;
        }
        setValidationError('');
        return true;
    };
    const handleSave = () => {
        if (!validateForm())
            return;
        const referencedFields = extractReferencedFields(expression);
        const columnCode = existingColumnCode || `formula_column_${Date.now()}`;
        const config = {
            fieldName,
            expression,
            referencedFields,
            columnCode,
        };
        onSave(config);
    };
    const handleCancel = () => {
        setFieldName(fieldLabel);
        setExpression(initialExpression || '');
        setValidationError('');
        onCancel();
    };
    const displayExpression = useMemo(() => {
        if (!expression.trim())
            return '';
        const fieldMap = new Map(availableFields.map((f) => [f.dataIndex, f.title]));
        return expression.replace(/\{([^}]+)\}/g, (_match, inner) => {
            const title = fieldMap.get(inner.trim());
            return title ? `{${title}}` : _match;
        });
    }, [expression, availableFields]);
    const hasExpression = expression.trim().length > 0;
    return (React.createElement(React.Fragment, null,
        React.createElement("div", { className: "formula-field-config-panel" },
            React.createElement("div", { className: "formula-field-config-header" },
                React.createElement("div", { className: "formula-field-config-header-left" },
                    React.createElement(CnIcon, { type: "function", style: { color: '#1677ff', fontSize: '16px' } }),
                    React.createElement("span", { className: "formula-field-config-title" }, $i18n.get({ id: 'FormulaField', dm: '公式字段' }))),
                React.createElement(CnIcon, { type: "close", size: "small", onClick: handleCancel, style: { cursor: 'pointer' } })),
            React.createElement("div", { className: "formula-field-config-content" },
                React.createElement("div", { className: "formula-field-config-section" },
                    React.createElement(CnInput, { ref: fieldNameInputRef, value: fieldName, onChange: setFieldName, placeholder: $i18n.get({ id: 'EnterFieldTitle', dm: '请输入字段标题' }), style: { width: '100%' } })),
                React.createElement("div", { className: "formula-field-config-section" },
                    React.createElement("div", { className: "formula-field-config-label" }, $i18n.get({ id: 'Formula', dm: '公式' })),
                    React.createElement("div", { className: "formula-field-edit-button", onClick: handleOpenEditorDialog },
                        React.createElement(CnIcon, { type: "edit", size: "small" }),
                        React.createElement("span", null, $i18n.get({ id: 'EditFormula', dm: '编辑公式' }))),
                    hasExpression && (React.createElement("div", { className: "formula-field-expression-preview" }, displayExpression)),
                    validationError && (React.createElement("div", { className: "formula-field-config-validation-error" }, validationError)))),
            React.createElement("div", { className: "formula-field-config-footer" },
                React.createElement("div", { style: { display: 'flex', gap: '8px' } },
                    React.createElement(CnButton, { onClick: handleCancel }, $i18n.get({ id: 'Cancel', dm: '取消' })),
                    React.createElement(CnButton, { type: "primary", onClick: handleSave }, $i18n.get({ id: 'OK', dm: '确定' }))))),
        React.createElement(CnDialog, { visible: editorDialogVisible, onClose: handleEditorDialogClose, title: React.createElement("div", { className: "formula-editor-dialog-title" },
                React.createElement("span", null, $i18n.get({ id: 'FormulaEditor', dm: '公式编辑器' })),
                React.createElement(CnIcon, { type: "help-color", size: 16, style: { marginLeft: '4px', cursor: 'pointer' } })), size: "medium", className: "formula-editor-dialog", footer: false },
            React.createElement("div", { className: "formula-editor-dialog-content" },
                React.createElement("div", { className: "formula-editor-dialog-editor-section" },
                    React.createElement("div", { className: "formula-editor-dialog-editor-wrapper" },
                        React.createElement(FormulaEditor, { ref: editorRef, value: pendingExpression, onChange: handleExpressionChange, fields: availableFields, placeholder: $i18n.get({
                                id: 'EnterAFormulaExpressionSuchAsSUM_1722066728',
                                dm: '输入公式表达式，如 =SUM({字段1}, {字段2})',
                            }), minHeight: 140 }),
                        React.createElement("div", { className: "formula-editor-dialog-editor-footer" },
                            previewResult !== null && (React.createElement("div", { className: "formula-editor-preview-result" },
                                React.createElement("span", { className: "formula-editor-preview-label" }, $i18n.get({ id: 'PreviewFirstRowResult', dm: '预览首行结果' })),
                                React.createElement("span", { className: "formula-editor-preview-tag" }, fieldName || $i18n.get({ id: 'FormulaField', dm: '公式字段' })),
                                React.createElement("span", { className: "formula-editor-preview-separator" }, ":"),
                                React.createElement("span", { className: "formula-editor-preview-value" }, previewResult))),
                            React.createElement(CnButton, { type: "primary", size: "small", onClick: handleEditorDialogConfirm }, $i18n.get({ id: 'OK', dm: '确定' }))))),
                React.createElement("div", { className: "formula-editor-dialog-bottom-panel" },
                    React.createElement("div", { className: "formula-editor-dialog-bottom-panel-content" },
                        React.createElement("div", { className: "formula-editor-dialog-tabs" },
                            React.createElement("span", { className: "formula-editor-dialog-tab active" }, $i18n.get({ id: 'FormulaEditor', dm: '公式编辑器' }))),
                        React.createElement("div", { className: "formula-editor-dialog-panel-body" },
                            React.createElement("div", { className: "formula-editor-dialog-fields" },
                                React.createElement("div", { className: "formula-editor-dialog-fields-list" },
                                    React.createElement("div", { className: "formula-editor-dialog-group-title" }, $i18n.get({ id: 'FieldReference', dm: '字段引用' })),
                                    availableFields.map((field) => (React.createElement(FieldReferenceItem, { key: field.dataIndex, field: field, editorRef: editorRef, onHover: (f) => handleHoverEnter({ type: 'field', data: f }), onLeave: handleHoverLeave, isActive: (hoveredItem === null || hoveredItem === void 0 ? void 0 : hoveredItem.type) === 'field' &&
                                            hoveredItem.data.dataIndex === field.dataIndex }))),
                                    availableFields.length === 0 && (React.createElement("span", { className: "formula-editor-dialog-no-fields" }, $i18n.get({ id: 'NoReferenceFieldsAvailable', dm: '暂无可引用字段' }))),
                                    groupedFunctions.map((group) => (React.createElement(React.Fragment, { key: group.category },
                                        React.createElement("div", { className: "formula-editor-dialog-group-title" }, group.label),
                                        group.functions.map((fn) => (React.createElement(FunctionReferenceItem, { key: fn.name, fn: fn, onInsert: () => handleInsertFunction(fn), onHover: (f) => handleHoverEnter({ type: 'function', data: f }), onLeave: handleHoverLeave, isActive: (hoveredItem === null || hoveredItem === void 0 ? void 0 : hoveredItem.type) === 'function' && hoveredItem.data.name === fn.name })))))))),
                            React.createElement("div", { className: "formula-editor-dialog-field-info", onMouseEnter: handleInfoPanelMouseEnter, onMouseLeave: handleInfoPanelMouseLeave },
                                React.createElement(InfoDetailPanel, { hoveredItem: hoveredItem })))))))));
}
