"use strict";
/**
 * LookupFieldDriver —— 引用字段驱动
 *
 * 功能参考钉表格的查找引用字段：
 * 通过引用其他数据表的字段，根据查找条件匹配记录，回填目标字段值。
 *
 * 设计要点：
 * 1. panelKind = 'inline'，用户选择后弹出配置面板。
 * 2. MaterializeMode = 'passive'，数据由后端查找引用服务填充。
 * 3. 配置包含：引用数据表、引用字段、字段描述与可检索能力（canSearch/model）。
 * 4. 配置持久化到 DataModel.customFields.lookupConfig，由视图保存链路统一落远端。
 * 5. `lookupFieldConfig.hiddenSubTable === true` 且配置了业务回调时，先回调再写本地/魔方；
 *    未开启 hiddenSubTable 时不走业务回调，保持原引用字段逻辑。
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LookupFieldDriver = void 0;
const i18n_1 = __importDefault(require("../../../../locales/i18n.js"));
const lookup_field_panel_adapter_1 = require("./panels/lookup-field-panel-adapter");
const lookup_search_config_event_1 = require("../../utils/lookup-search-config-event");
const lookup_column_code_1 = require("../../utils/lookup-column-code");
const arms_hot_tag_log_1 = require("../../../../utils/arms/arms-hot-tag-log.js");
/**
 * 将各种类型的 canSearch 值统一转换为字符串 'true' 或 'false'
 * @param raw - 待转换的原始值，可能来自不同数据源，类型不确定
 * @returns 标准化后的字符串 'true' | 'false'
 */
function toCallbackCanSearchString(raw) {
    if (raw === true || raw === 'true' || raw === 'TRUE' || raw === 1 || raw === '1') {
        return 'true';
    }
    return 'false';
}
/**
 * 构建业务回调所需的字段摘要数据
 * 仅提取子表字段的关键信息，避免传递冗余配置给业务方
 * @param lookupRow - 引用字段的完整配置
 * @returns 适配业务回调接口的参数对象
 */
function buildLookupCallbackPayload(lookupRow) {
    var _a, _b;
    const fallbackModel = { props: {} };
    const model = lookupRow.model && typeof lookupRow.model === 'object'
        ? lookupRow.model
        : fallbackModel;
    return {
        model,
        label: (_b = (_a = lookupRow.targetFieldName) !== null && _a !== void 0 ? _a : lookupRow.targetFieldCode) !== null && _b !== void 0 ? _b : '',
        canSearch: toCallbackCanSearchString(lookupRow.canSearch),
        value: lookupRow.targetFieldCode,
    };
}
/**
 * 引用字段驱动类
 *
 * 实现 FieldDriver 接口，提供引用字段的完整生命周期管理，包括：
 * 创建、编辑、删除、数据水合、视图挂载等能力。
 */
class LookupFieldDriver {
    /**
     * 获取引用字段的元数据信息
     * 用于字段类型注册、选择面板展示等场景
     * @returns 包含字段类型标识、展示名称、分类、排序权重、图标等元信息
     */
    getMeta() {
        return {
            type: 'lookup',
            label: i18n_1.default.get({ id: 'ReferenceField', dm: '引用字段' }),
            category: 'regular',
            order: 101,
            icon: 'lookup',
            iconType: 'reference-field',
            materializeMode: 'passive',
        };
    }
    /**
     * 获取引用字段的 UI 贡献配置
     * 定义字段在选择器面板中的展示项、创建/编辑面板组件及面板交互模式
     * @returns UI 贡献配置对象，包含 selectorItem、面板组件和面板类型
     */
    getUiContribution() {
        const meta = this.getMeta();
        return {
            selectorItem: {
                type: meta.type,
                label: meta.label,
                icon: meta.icon,
                iconType: meta.iconType,
                color: undefined,
                category: meta.category,
                order: meta.order,
            },
            createPanel: lookup_field_panel_adapter_1.LookupFieldPanelAdapter,
            editPanel: lookup_field_panel_adapter_1.LookupFieldPanelAdapter,
            panelKind: 'inline',
        };
    }
    /**
     * 创建引用字段的默认配置
     * 用于新建字段时初始化空白表单状态
     * @returns 所有字段为空/默认值的配置对象
     */
    createDefaultConfig() {
        return {
            fieldName: '',
            sourceTableId: '',
            sourceTableName: '',
            targetFieldCode: '',
            targetFieldName: '',
            columnCode: '',
            description: '',
            canSearch: false,
            model: {},
        };
    }
    /**
     * 校验引用字段配置的完整性
     * 依次检查字段名称、数据表选择、引用字段选择是否已填写
     * @param config - 待校验的引用字段配置
     * @returns 校验结果对象，valid 为 false 时包含 error 提示信息
     */
    validateConfig(config) {
        var _a;
        if (!((_a = config.fieldName) === null || _a === void 0 ? void 0 : _a.trim())) {
            return {
                valid: false,
                error: i18n_1.default.get({ id: 'PleaseEnterAFieldName', dm: '请输入字段名称' }),
            };
        }
        if (!config.sourceTableId) {
            return {
                valid: false,
                error: i18n_1.default.get({ id: 'PleaseSelectADataTable', dm: '请选择数据表' }),
            };
        }
        if (!config.targetFieldCode) {
            return {
                valid: false,
                error: i18n_1.default.get({ id: 'PleaseSelectAReferenceField', dm: '请选择引用字段' }),
            };
        }
        return { valid: true };
    }
    /**
     * 持久化引用字段元数据（创建流程）
     *
     * 执行顺序：
     * 1. 生成或复用 columnCode 作为字段唯一标识
     * 2. 校验是否有重复引用
     * 3. 若处于 hiddenSubTable 模式，调用业务方 addFieldCallback
     * 4. 写入 DataModel 的 lookupConfig
     * 5. 发出搜索配置更新事件通知 CnAiFilter
     * 6. 记录埋点日志
     *
     * @param config - 用户在面板中填写的引用字段配置
     * @param ctx - 字段操作上下文，包含 dataModel、eventBus、services 等
     * @returns 创建成功后的字段记录，包含 id、类型、名称、配置及运行时信息
     */
    async persistMeta(config, ctx) {
        var _a, _b, _c, _d, _e;
        const columnCode = config.columnCode || (0, lookup_column_code_1.buildLookupColumnCode)(config.sourceTableId, config.targetFieldCode);
        this.ensureNoDuplicateLookup(ctx, config.sourceTableId, config.targetFieldCode, columnCode);
        const lookupConfig = {
            ...config,
            columnCode,
            fieldType: 'lookup',
        };
        const addCb = this.shouldInvokeLookupBizCallbacks(ctx)
            ? (_b = (_a = ctx.services) === null || _a === void 0 ? void 0 : _a.lookup) === null || _b === void 0 ? void 0 : _b.addFieldCallback
            : undefined;
        if (addCb) {
            await addCb(buildLookupCallbackPayload(lookupConfig));
        }
        ctx.dataModel.setCustomFieldLookupConfig(columnCode, lookupConfig);
        ctx.eventBus.emit(ctx.cnAiListEventNames.LOOKUP_FIELD_SEARCH_CONFIG_UPDATE, (0, lookup_search_config_event_1.createLookupSearchConfigUpdatePayload)((_c = ctx.dataModel.customFields) === null || _c === void 0 ? void 0 : _c.lookupConfig, 'create'));
        (0, arms_hot_tag_log_1.armsHottagLog)({
            hottag: 'cn-ai-table.lookupField.create',
            name: i18n_1.default.get({ id: 'CreateCitationField', dm: '创建引用字段' }),
            c6: columnCode,
            c7: String((_d = ctx.dataModel.tableId) !== null && _d !== void 0 ? _d : ''),
            c8: config.sourceTableId,
            c9: config.targetFieldCode,
            c10: ((_e = ctx.lookupFieldConfig) === null || _e === void 0 ? void 0 : _e.hiddenSubTable) === true ? 'hiddenSubTable' : 'default',
        });
        return {
            id: columnCode,
            type: 'lookup',
            name: config.fieldName,
            config: { ...lookupConfig },
            runtime: { mode: 'passive' },
        };
    }
    /**
     * 构建表格列定义并注册到 DataModel
     * 将字段记录转化为表格组件可消费的列配置对象
     * @param record - 字段记录，包含 id 和 name 等信息
     * @param ctx - 字段操作上下文，用于访问 dataModel.addColumn
     * @returns 表格列定义对象，包含 dataIndex、title、header、accessorKey、format
     */
    buildColumnDef(record, ctx) {
        const colDef = {
            dataIndex: record.id,
            title: record.name,
            header: record.name,
            accessorKey: record.id,
            format: 'lookup',
        };
        ctx.dataModel.addColumn(colDef);
        return colDef;
    }
    /**
     * 将字段挂载到指定视图的列顺序中
     * 如果字段已存在于 columnOrder 则跳过，避免重复添加
     * @param record - 字段记录，record.id 用于加入列顺序数组
     * @param ctx - 字段操作上下文，ctx.viewId 指定目标视图
     */
    attachToView(record, ctx) {
        const viewConfig = ctx.dataModel.getViewConfig(ctx.viewId);
        const currentColumnOrder = viewConfig.columnOrder || [];
        const nextColumnOrder = currentColumnOrder.includes(record.id)
            ? currentColumnOrder
            : [...currentColumnOrder, record.id];
        ctx.dataModel.setViewConfig(ctx.viewId, { columnOrder: nextColumnOrder }, true);
    }
    /**
     * 物化数据（空实现）
     * 引用字段为 passive 模式，数据由后端查找引用服务异步填充，前端无需主动物化
     */
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    async materializeData() { }
    /**
     * 更新引用字段元数据（编辑流程）
     *
     * 仅允许修改 fieldName 和 description，sourceTableId / targetFieldCode 不可变更。
     * 执行顺序：
     * 1. 获取已有配置作为不可变基准
     * 2. 校验重复引用
     * 3. 合并可编辑字段并写入 DataModel
     * 4. 发出搜索配置更新事件
     * 5. 同步更新列定义中的 title/header
     * 6. 触发远端视图同步
     * 7. 记录埋点日志
     *
     * @param columnId - 要更新的字段 columnCode 标识
     * @param config - 用户修改后的配置（仅 fieldName/description 生效）
     * @param ctx - 字段操作上下文
     * @returns 更新后的字段记录
     */
    async updateMeta(columnId, config, ctx) {
        var _a, _b, _c, _d, _e, _f;
        const existingConfig = ctx.dataModel.getCustomFieldLookupConfig(columnId);
        const immutableConfig = existingConfig || config;
        this.ensureNoDuplicateLookup(ctx, immutableConfig.sourceTableId, immutableConfig.targetFieldCode, columnId);
        const lookupConfig = {
            ...immutableConfig,
            fieldName: config.fieldName,
            description: (_a = config.description) !== null && _a !== void 0 ? _a : immutableConfig.description,
            columnCode: columnId,
            fieldType: 'lookup',
        };
        ctx.dataModel.setCustomFieldLookupConfig(columnId, lookupConfig);
        ctx.eventBus.emit(ctx.cnAiListEventNames.LOOKUP_FIELD_SEARCH_CONFIG_UPDATE, (0, lookup_search_config_event_1.createLookupSearchConfigUpdatePayload)((_b = ctx.dataModel.customFields) === null || _b === void 0 ? void 0 : _b.lookupConfig, 'update'));
        const colDefs = ctx.dataModel.columnDefinitions || [];
        const colIdx = colDefs.findIndex((c) => c.dataIndex === columnId);
        if (colIdx >= 0) {
            colDefs[colIdx] = { ...colDefs[colIdx], title: config.fieldName, header: config.fieldName };
            ctx.dataModel.setColumnDefinitions([...colDefs]);
        }
        (_d = (_c = ctx.dataModel).updateRemoteViews) === null || _d === void 0 ? void 0 : _d.call(_c);
        (0, arms_hot_tag_log_1.armsHottagLog)({
            hottag: 'cn-ai-table.lookupField.update',
            name: i18n_1.default.get({ id: 'UpdateCitationField', dm: '更新引用字段' }),
            c6: columnId,
            c7: String((_e = ctx.dataModel.tableId) !== null && _e !== void 0 ? _e : ''),
            c8: lookupConfig.sourceTableId,
            c9: lookupConfig.targetFieldCode,
            c10: ((_f = ctx.lookupFieldConfig) === null || _f === void 0 ? void 0 : _f.hiddenSubTable) === true ? 'hiddenSubTable' : 'default',
        });
        return {
            id: columnId,
            type: 'lookup',
            name: config.fieldName,
            config: { ...lookupConfig },
            runtime: { mode: 'passive' },
        };
    }
    /**
     * 删除引用字段
     *
     * 执行顺序：
     * 1. 获取已有配置用于回调参数构建
     * 2. 若处于 hiddenSubTable 模式，调用业务方 deleteFieldCallback
     * 3. 从 DataModel 中彻底移除字段（列定义、视图配置、自定义字段）
     * 4. 发出搜索配置更新事件
     * 5. 记录埋点日志
     *
     * @param columnId - 要删除的字段 columnCode 标识
     * @param ctx - 字段操作上下文
     */
    async remove(columnId, ctx) {
        var _a, _b, _c, _d, _e, _f, _g;
        const existing = ctx.dataModel.getCustomFieldLookupConfig(columnId);
        const delCb = this.shouldInvokeLookupBizCallbacks(ctx)
            ? (_b = (_a = ctx.services) === null || _a === void 0 ? void 0 : _a.lookup) === null || _b === void 0 ? void 0 : _b.deleteFieldCallback
            : undefined;
        if (delCb && existing) {
            await delCb(buildLookupCallbackPayload(existing));
        }
        this.removeFieldFromDataModel(columnId, ctx);
        ctx.eventBus.emit(ctx.cnAiListEventNames.LOOKUP_FIELD_SEARCH_CONFIG_UPDATE, (0, lookup_search_config_event_1.createLookupSearchConfigUpdatePayload)((_c = ctx.dataModel.customFields) === null || _c === void 0 ? void 0 : _c.lookupConfig, 'delete'));
        (0, arms_hot_tag_log_1.armsHottagLog)({
            hottag: 'cn-ai-table.lookupField.delete',
            name: i18n_1.default.get({ id: 'DeleteReferenceField', dm: '删除引用字段' }),
            c6: columnId,
            c7: String((_d = ctx.dataModel.tableId) !== null && _d !== void 0 ? _d : ''),
            c8: existing ? String((_e = existing.sourceTableId) !== null && _e !== void 0 ? _e : '') : '',
            c9: existing ? String((_f = existing.targetFieldCode) !== null && _f !== void 0 ? _f : '') : '',
            c10: ((_g = ctx.lookupFieldConfig) === null || _g === void 0 ? void 0 : _g.hiddenSubTable) === true ? 'hiddenSubTable' : 'default',
        });
    }
    /**
     * 从持久化配置中水合（恢复）字段记录
     * 用于页面加载时从 DataModel 中读取已保存的 lookupConfig 并重建 FieldRecord
     * @param columnId - 字段的 columnCode 标识
     * @param ctx - 字段操作上下文
     * @returns 水合后的字段记录；若配置不存在则返回 undefined
     */
    hydrate(columnId, ctx) {
        const lookupConfig = ctx.dataModel.getCustomFieldLookupConfig(columnId);
        if (!lookupConfig)
            return undefined;
        return {
            id: columnId,
            type: 'lookup',
            name: lookupConfig.fieldName,
            config: lookupConfig,
            runtime: { mode: 'passive' },
        };
    }
    /**
     * 判断是否应调用业务方的 add/deleteFieldCallback 回调
     * 仅在 hiddenSubTable 模式下才触发业务回调，避免非隐藏子表场景下产生副作用
     * @param ctx - 字段操作上下文，包含 lookupFieldConfig 等全局配置
     * @returns true 表示需要调用业务回调
     */
    shouldInvokeLookupBizCallbacks(ctx) {
        var _a;
        return ((_a = ctx.lookupFieldConfig) === null || _a === void 0 ? void 0 : _a.hiddenSubTable) === true;
    }
    /**
     * 校验引用字段是否存在重复配置
     * 同一数据表的同一字段不允许被重复引用（排除自身编辑场景）
     * @param ctx - 字段操作上下文
     * @param sourceTableId - 引用的源数据表 ID
     * @param targetFieldCode - 引用的目标字段 code
     * @param selfColumnCode - 当前字段自身的 columnCode，编辑时排除自身
     * @throws 如果检测到重复引用，抛出错误提示用户
     */
    ensureNoDuplicateLookup(ctx, sourceTableId, targetFieldCode, selfColumnCode) {
        var _a, _b;
        const lookupConfigMap = ((_b = (_a = ctx.dataModel) === null || _a === void 0 ? void 0 : _a.customFields) === null || _b === void 0 ? void 0 : _b.lookupConfig) || {};
        const hasDuplicate = Object.entries(lookupConfigMap).some(([columnCode, item]) => {
            if (selfColumnCode && columnCode === selfColumnCode) {
                return false;
            }
            return (item === null || item === void 0 ? void 0 : item.sourceTableId) === sourceTableId && (item === null || item === void 0 ? void 0 : item.targetFieldCode) === targetFieldCode;
        });
        if (hasDuplicate) {
            throw new Error(i18n_1.default.get({ id: 'ThisFieldHasAlreadyBeenAdded', dm: '该字段已经添加' }));
        }
    }
    /**
     * 从 DataModel 中彻底移除指定字段的所有痕迹
     *
     * 清理范围：
     * - 列定义（columnDefinitions）
     * - 自定义字段配置（customFields）
     * - 所有视图配置中的引用：columnOrder、hiddenColumns、filter、sort、group、colorFill
     * - 触发远端视图同步
     *
     * @param columnId - 要移除的字段 columnCode 标识
     * @param ctx - 字段操作上下文
     */
    removeFieldFromDataModel(columnId, ctx) {
        var _a, _b;
        const { dataModel } = ctx;
        const newColumnDefinitions = dataModel.columnDefinitions.filter((col) => col.dataIndex !== columnId);
        dataModel.setColumnDefinitions(newColumnDefinitions);
        (_a = dataModel.removeCustomField) === null || _a === void 0 ? void 0 : _a.call(dataModel, columnId);
        dataModel.viewConfigs.forEach((config, viewId) => {
            const currentColumnOrder = config.columnOrder || [];
            const currentHiddenColumns = config.hiddenColumns || [];
            dataModel.setViewConfig(viewId, {
                columnOrder: currentColumnOrder.filter((col) => col !== columnId),
                hiddenColumns: currentHiddenColumns.filter((col) => col !== columnId),
                filter: (config.filter || []).filter((rule) => rule.field !== columnId),
                sort: (config.sort || []).filter((rule) => rule.field !== columnId),
                group: (config.group || []).filter((rule) => rule.field !== columnId),
                colorFill: (config.colorFill || []).filter((rule) => rule.field !== columnId),
            });
        });
        (_b = dataModel.updateRemoteViews) === null || _b === void 0 ? void 0 : _b.call(dataModel);
    }
}
exports.LookupFieldDriver = LookupFieldDriver;
