/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var collectors_exports = {};
__export(collectors_exports, {
  collectFlowRegistryRunJsAuthoringErrors: () => collectFlowRegistryRunJsAuthoringErrors,
  collectRunJsAuthoringErrors: () => collectRunJsAuthoringErrors
});
module.exports = __toCommonJS(collectors_exports);
var _ = __toESM(require("lodash"));
var import_chart_config = require("../chart-config");
var import_errors = require("./runtime/errors");
var import_source_budget = require("./runtime/source-budget");
var import_surface = require("./runtime/surface");
var import_inspect = require("./inspect");
const HIDDEN_POPUP_SETTINGS_KEYS_BY_BLOCK_TYPE = {
  calendar: ["quickCreatePopup", "eventPopup"],
  kanban: ["quickCreatePopup", "cardPopup"]
};
function asPlainRecord(value) {
  return _.isPlainObject(value) ? value : void 0;
}
function collectRunJsAuthoringErrors(actionName, values, context = {}) {
  var _a, _b;
  const errors = [];
  const validationContext = {
    ...context,
    authoringActionName: actionName,
    runJsSourceBudget: (0, import_source_budget.createRunJsSourceBudget)()
  };
  if (!_.isPlainObject(values)) {
    return errors;
  }
  if (actionName === "configure") {
    collectConfigureRunJsErrors(values, validationContext, errors);
    collectReactionRunJsErrors(
      values.reaction,
      "$.reaction",
      errors,
      validationContext.runJsSourceBudget,
      validationContext
    );
    collectReactionRunJsErrors(
      (_a = values.changes) == null ? void 0 : _a.reaction,
      "$.changes.reaction",
      errors,
      validationContext.runJsSourceBudget,
      validationContext
    );
    return (0, import_errors.dedupeErrors)(errors);
  }
  if (actionName === "applyBlueprint") {
    collectChartAssetRunJsErrors(
      (_b = values.assets) == null ? void 0 : _b.charts,
      "$.assets.charts",
      errors,
      validationContext.runJsSourceBudget,
      validationContext
    );
  }
  getAuthoringBlocks(actionName, values).forEach(
    ({ block, path }) => collectBlockRunJsErrors(block, path, validationContext, errors)
  );
  collectReactionRunJsErrors(
    values.reaction,
    "$.reaction",
    errors,
    validationContext.runJsSourceBudget,
    validationContext
  );
  return (0, import_errors.dedupeErrors)(errors);
}
function collectFlowRegistryRunJsAuthoringErrors(flowRegistry, path = "$.flowRegistry", context = {}) {
  const errors = [];
  collectFlowRegistryRunJsErrors(flowRegistry, path, errors, (0, import_source_budget.createRunJsSourceBudget)(), context);
  return (0, import_errors.dedupeErrors)(errors);
}
function collectConfigureRunJsErrors(values, context, errors) {
  var _a;
  const changes = values.changes;
  if (!_.isPlainObject(changes)) {
    return;
  }
  const modelUse = (0, import_surface.resolveConfigureModelUse)(context.currentNode);
  const surfaceStyle = (0, import_surface.resolveModelSurfaceStyle)(modelUse);
  const hostBlockType = (0, import_surface.resolveConfigureBlockType)(context);
  if (typeof changes.code === "string" && changes.code.trim()) {
    errors.push(
      ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
        {
          code: changes.code,
          path: "$.changes.code",
          modelUse: modelUse || "unknown",
          surfaceStyle
        },
        context.runJsSourceBudget,
        context
      )
    );
  }
  if (hostBlockType === "chart") {
    collectChartRawRunJsErrors(changes, "$.changes", errors, context.runJsSourceBudget, context);
    collectChartLegacyConfigureRunJsErrors(
      changes.configure,
      "$.changes.configure",
      errors,
      context.runJsSourceBudget,
      context
    );
  }
  const recursiveChanges = {
    ...changes,
    type: hostBlockType
  };
  delete recursiveChanges.code;
  delete recursiveChanges.source;
  if (_.isPlainObject(recursiveChanges.settings)) {
    recursiveChanges.settings = _.omit(recursiveChanges.settings, ["code", "source"]);
  }
  collectBlockRunJsErrors(recursiveChanges, "$.changes", context, errors);
  (_a = HIDDEN_POPUP_SETTINGS_KEYS_BY_BLOCK_TYPE[hostBlockType]) == null ? void 0 : _a.forEach((key) => {
    var _a2, _b;
    collectBlockListRunJsErrors((_a2 = changes == null ? void 0 : changes[key]) == null ? void 0 : _a2.blocks, `$.changes.${key}.blocks`, context, errors);
    collectReactionRunJsErrors(
      (_b = changes == null ? void 0 : changes[key]) == null ? void 0 : _b.reaction,
      `$.changes.${key}.reaction`,
      errors,
      context.runJsSourceBudget,
      context
    );
  });
}
function createRunJsResourceContext(context, resourceInit) {
  const collectionName = (0, import_surface.normalizeText)(resourceInit == null ? void 0 : resourceInit.collectionName);
  if (!collectionName) {
    return context;
  }
  const dataSourceKey = (0, import_surface.normalizeText)(resourceInit == null ? void 0 : resourceInit.dataSourceKey) || (0, import_surface.normalizeText)(context.currentDataSourceKey || context.hostDataSourceKey) || "main";
  return {
    ...context,
    currentDataSourceKey: dataSourceKey,
    currentCollectionName: collectionName
  };
}
function getRunJsBlockResourceInit(block, blockType) {
  var _a, _b;
  const resourceInit = asPlainRecord(block == null ? void 0 : block.resourceInit);
  const resource = asPlainRecord(block == null ? void 0 : block.resource);
  const chartResourceInit = blockType === "chart" ? (0, import_chart_config.getChartBuilderResourceInit)(((_a = block == null ? void 0 : block.settings) == null ? void 0 : _a.configure) || (block == null ? void 0 : block.configure) || ((_b = block == null ? void 0 : block.chartSettings) == null ? void 0 : _b.configure)) : null;
  return {
    dataSourceKey: (block == null ? void 0 : block.dataSourceKey) || (resource == null ? void 0 : resource.dataSourceKey) || (resourceInit == null ? void 0 : resourceInit.dataSourceKey) || (chartResourceInit == null ? void 0 : chartResourceInit.dataSourceKey),
    collectionName: (block == null ? void 0 : block.collection) || (resource == null ? void 0 : resource.collectionName) || (resourceInit == null ? void 0 : resourceInit.collectionName) || (chartResourceInit == null ? void 0 : chartResourceInit.collectionName)
  };
}
function getAuthoringBlocks(actionName, values) {
  if (actionName === "addBlock") {
    return [{ block: values, path: "$" }];
  }
  if (actionName === "addBlocks" || actionName === "compose") {
    return _.castArray(values.blocks || []).map((block, index) => ({
      block,
      path: `$.blocks[${index}]`
    }));
  }
  if (actionName === "applyBlueprint") {
    return _.castArray(values.tabs || []).flatMap(
      (tab, tabIndex) => _.castArray((tab == null ? void 0 : tab.blocks) || []).map((block, blockIndex) => ({
        block,
        path: `$.tabs[${tabIndex}].blocks[${blockIndex}]`
      }))
    );
  }
  return [];
}
function collectBlockRunJsErrors(block, path, context, errors) {
  var _a, _b, _c, _d;
  if (!_.isPlainObject(block)) {
    return;
  }
  const blockType = (0, import_surface.resolvePublicBlockType)(block.type || block.use);
  const blockContext = createRunJsResourceContext(context, getRunJsBlockResourceInit(block, blockType));
  if (blockType === "jsBlock") {
    collectRunJsSources(block, path, blockContext).forEach((source) => {
      errors.push(
        ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
          {
            code: source.code,
            path: source.path,
            modelUse: "JSBlockModel",
            surfaceStyle: "render"
          },
          blockContext.runJsSourceBudget,
          blockContext
        )
      );
    });
  }
  if (blockType === "chart") {
    collectChartRawRunJsErrors(
      block.settings,
      `${path}.settings`,
      errors,
      blockContext.runJsSourceBudget,
      blockContext
    );
    collectChartLegacyConfigureRunJsErrors(
      (_a = block.settings) == null ? void 0 : _a.configure,
      `${path}.settings.configure`,
      errors,
      blockContext.runJsSourceBudget,
      blockContext
    );
  }
  collectFieldListRunJsErrors(block.fields, `${path}.fields`, blockType, blockContext, errors);
  _.castArray(block.fieldGroups || []).forEach((group, groupIndex) => {
    collectFieldListRunJsErrors(
      group == null ? void 0 : group.fields,
      `${path}.fieldGroups[${groupIndex}].fields`,
      blockType,
      blockContext,
      errors
    );
  });
  collectActionListRunJsErrors(block.actions, `${path}.actions`, blockType, "actions", blockContext, errors);
  collectActionListRunJsErrors(
    block.recordActions,
    `${path}.recordActions`,
    blockType,
    "recordActions",
    blockContext,
    errors
  );
  collectReactionRunJsErrors(block.reaction, `${path}.reaction`, errors, blockContext.runJsSourceBudget, blockContext);
  collectFlowRegistryRunJsErrors(
    block.flowRegistry,
    `${path}.flowRegistry`,
    errors,
    blockContext.runJsSourceBudget,
    blockContext
  );
  collectBlockListRunJsErrors(block.blocks, `${path}.blocks`, blockContext, errors);
  collectBlockListRunJsErrors((_b = block.popup) == null ? void 0 : _b.blocks, `${path}.popup.blocks`, blockContext, errors);
  collectReactionRunJsErrors(
    (_c = block.popup) == null ? void 0 : _c.reaction,
    `${path}.popup.reaction`,
    errors,
    blockContext.runJsSourceBudget,
    blockContext
  );
  (_d = HIDDEN_POPUP_SETTINGS_KEYS_BY_BLOCK_TYPE[blockType]) == null ? void 0 : _d.forEach((key) => {
    var _a2, _b2, _c2, _d2;
    collectBlockListRunJsErrors((_b2 = (_a2 = block.settings) == null ? void 0 : _a2[key]) == null ? void 0 : _b2.blocks, `${path}.settings.${key}.blocks`, blockContext, errors);
    collectReactionRunJsErrors(
      (_d2 = (_c2 = block.settings) == null ? void 0 : _c2[key]) == null ? void 0 : _d2.reaction,
      `${path}.settings.${key}.reaction`,
      errors,
      blockContext.runJsSourceBudget,
      blockContext
    );
  });
}
function collectBlockListRunJsErrors(blocks, path, context, errors) {
  if (!Array.isArray(blocks)) {
    return;
  }
  blocks.forEach((block, index) => collectBlockRunJsErrors(block, `${path}[${index}]`, context, errors));
}
function collectFieldListRunJsErrors(fields, path, blockType, context, errors) {
  if (!Array.isArray(fields)) {
    return;
  }
  fields.forEach((field, index) => {
    var _a, _b;
    const fieldPath = `${path}[${index}]`;
    if (!_.isPlainObject(field)) {
      return;
    }
    const type = (0, import_surface.normalizeText)(field.type);
    const renderer = (0, import_surface.normalizeText)(field.renderer);
    const modelUse = (0, import_surface.resolveFieldModelUse)(type, renderer, blockType);
    if (modelUse) {
      collectRunJsSources(field, fieldPath, context).forEach((source) => {
        errors.push(
          ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
            {
              code: source.code,
              path: source.path,
              modelUse,
              surfaceStyle: "render"
            },
            context.runJsSourceBudget,
            context
          )
        );
      });
    }
    collectReactionRunJsErrors(field.reaction, `${fieldPath}.reaction`, errors, context.runJsSourceBudget, context);
    collectActionListRunJsErrors(field.actions, `${fieldPath}.actions`, blockType, "actions", context, errors);
    collectBlockListRunJsErrors((_a = field.popup) == null ? void 0 : _a.blocks, `${fieldPath}.popup.blocks`, context, errors);
    collectReactionRunJsErrors(
      (_b = field.popup) == null ? void 0 : _b.reaction,
      `${fieldPath}.popup.reaction`,
      errors,
      context.runJsSourceBudget,
      context
    );
  });
}
function collectActionListRunJsErrors(actions, path, blockType, slot, context, errors) {
  if (!Array.isArray(actions)) {
    return;
  }
  actions.forEach((action, index) => {
    var _a, _b, _c, _d;
    const actionPath = `${path}[${index}]`;
    if (!_.isPlainObject(action)) {
      return;
    }
    const actionType = (0, import_surface.normalizeActionType)(action.type || action.key || action.action || action.use);
    const modelUse = (0, import_surface.resolveActionModelUse)(actionType, blockType, slot);
    if (modelUse) {
      collectRunJsSources(action, actionPath, context).forEach((source) => {
        errors.push(
          ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
            {
              code: source.code,
              path: source.path,
              modelUse,
              surfaceStyle: (0, import_surface.resolveModelSurfaceStyle)(modelUse)
            },
            context.runJsSourceBudget,
            context
          )
        );
      });
    }
    collectReactionRunJsErrors(action.reaction, `${actionPath}.reaction`, errors, context.runJsSourceBudget, context);
    collectBlockListRunJsErrors((_a = action.popup) == null ? void 0 : _a.blocks, `${actionPath}.popup.blocks`, context, errors);
    collectReactionRunJsErrors(
      (_b = action.popup) == null ? void 0 : _b.reaction,
      `${actionPath}.popup.reaction`,
      errors,
      context.runJsSourceBudget,
      context
    );
    collectBlockListRunJsErrors((_c = action.openView) == null ? void 0 : _c.blocks, `${actionPath}.openView.blocks`, context, errors);
    collectReactionRunJsErrors(
      (_d = action.openView) == null ? void 0 : _d.reaction,
      `${actionPath}.openView.reaction`,
      errors,
      context.runJsSourceBudget,
      context
    );
  });
}
function collectChartAssetRunJsErrors(charts, path, errors, budget, context = {}) {
  if (!_.isPlainObject(charts)) {
    return;
  }
  Object.entries(charts).forEach(([key, asset]) => {
    if (!_.isPlainObject(asset)) {
      return;
    }
    collectChartRawRunJsErrors(
      asset,
      `${path}.${key}`,
      errors,
      budget,
      createRunJsResourceContext(context, (0, import_chart_config.getChartBuilderResourceInit)(asset))
    );
  });
}
function collectChartLegacyConfigureRunJsErrors(configure, path, errors, budget, context = {}) {
  if (!_.isPlainObject(configure)) {
    return;
  }
  const chartContext = createRunJsResourceContext(context, (0, import_chart_config.getChartBuilderResourceInit)(configure));
  const chart = _.isPlainObject(configure.chart) ? configure.chart : void 0;
  const option = _.isPlainObject(chart == null ? void 0 : chart.option) ? chart.option : void 0;
  const events = _.isPlainObject(chart == null ? void 0 : chart.events) ? chart.events : void 0;
  collectChartOptionRunJsErrors(option == null ? void 0 : option.raw, `${path}.chart.option.raw`, errors, budget, chartContext);
  collectChartEventsRunJsErrors(events == null ? void 0 : events.raw, `${path}.chart.events.raw`, errors, budget, chartContext);
}
function collectChartRawRunJsErrors(value, path, errors, budget, context = {}) {
  if (!_.isPlainObject(value)) {
    return;
  }
  const chartContext = createRunJsResourceContext(context, (0, import_chart_config.getChartBuilderResourceInit)(value));
  const visual = _.isPlainObject(value.visual) ? value.visual : void 0;
  const events = _.isPlainObject(value.events) ? value.events : void 0;
  collectChartOptionRunJsErrors(visual == null ? void 0 : visual.raw, `${path}.visual.raw`, errors, budget, chartContext);
  collectChartEventsRunJsErrors(events == null ? void 0 : events.raw, `${path}.events.raw`, errors, budget, chartContext);
}
function collectChartOptionRunJsErrors(code, path, errors, budget, context = {}) {
  if (typeof code !== "string" || !code.trim()) {
    return;
  }
  errors.push(
    ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
      {
        code,
        path,
        modelUse: "ChartOptionModel",
        surfaceStyle: "value"
      },
      budget,
      context
    )
  );
}
function collectChartEventsRunJsErrors(code, path, errors, budget, context = {}) {
  if (typeof code !== "string" || !code.trim()) {
    return;
  }
  errors.push(
    ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
      {
        code,
        path,
        modelUse: "ChartEventsModel",
        surfaceStyle: "action"
      },
      budget,
      context
    )
  );
}
function collectReactionRunJsErrors(reaction, path, errors, budget, context = {}) {
  if (!reaction || !_.isPlainObject(reaction) && !Array.isArray(reaction)) {
    return;
  }
  const visit = (value, valuePath) => {
    var _a, _b, _c, _d, _e;
    if (Array.isArray(value)) {
      value.forEach((item, index) => visit(item, `${valuePath}[${index}]`));
      return;
    }
    if (!_.isPlainObject(value)) {
      return;
    }
    if (value.source === "runjs" && typeof value.code === "string" && value.code.trim()) {
      errors.push(
        ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
          {
            code: value.code,
            path: `${valuePath}.code`,
            surface: "reaction.value-runjs",
            surfaceStyle: "value"
          },
          budget,
          context
        )
      );
    }
    const actionType = (0, import_surface.normalizeText)(value.type || value.name);
    if (actionType === "runjs" || /runjs/i.test(actionType)) {
      const code = typeof value.code === "string" ? value.code : typeof ((_b = (_a = value.params) == null ? void 0 : _a.value) == null ? void 0 : _b.script) === "string" ? value.params.value.script : typeof ((_c = value.params) == null ? void 0 : _c.code) === "string" ? value.params.code : "";
      if (code.trim()) {
        const codePath = typeof value.code === "string" ? `${valuePath}.code` : typeof ((_e = (_d = value.params) == null ? void 0 : _d.value) == null ? void 0 : _e.script) === "string" ? `${valuePath}.params.value.script` : `${valuePath}.params.code`;
        errors.push(
          ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
            {
              code,
              path: codePath,
              surface: "linkage.execute-javascript",
              surfaceStyle: "action"
            },
            budget,
            context
          )
        );
      }
    }
    Object.entries(value).forEach(([key, child]) => {
      if (key === "code" || key === "params") {
        return;
      }
      visit(child, `${valuePath}.${key}`);
    });
  };
  visit(reaction, path);
}
function collectFlowRegistryRunJsErrors(flowRegistry, path, errors, budget, context = {}) {
  const registry = asPlainRecord(flowRegistry);
  if (!registry) {
    return;
  }
  Object.entries(registry).forEach(([flowKey, flowValue]) => {
    const flow = asPlainRecord(flowValue);
    if (!flow) {
      return;
    }
    const steps = asPlainRecord(flow.steps) || {};
    Object.entries(steps).forEach(([stepKey, stepValue]) => {
      const step = asPlainRecord(stepValue);
      if (!step || (0, import_surface.normalizeText)(step.use || step.type || step.action || step.key) !== "runjs") {
        return;
      }
      collectEventFlowRunJsStepErrors(step, `${path}.${flowKey}.steps.${stepKey}`, errors, budget, context);
    });
  });
}
function collectEventFlowRunJsStepErrors(step, path, errors, budget, context = {}) {
  var _a, _b, _c, _d, _e, _f;
  const addSource = (code, sourcePath) => {
    if (typeof code !== "string" || !code.trim()) {
      return;
    }
    errors.push(
      ...(0, import_inspect.inspectRunJsAuthoringCodeForWrite)(
        {
          code,
          path: sourcePath,
          surface: "event-flow.execute-javascript",
          modelUse: "JSActionModel",
          surfaceStyle: "action"
        },
        budget,
        context
      )
    );
  };
  addSource((_a = step.defaultParams) == null ? void 0 : _a.code, `${path}.defaultParams.code`);
  addSource((_b = step.params) == null ? void 0 : _b.code, `${path}.params.code`);
  addSource((_d = (_c = step.defaultParams) == null ? void 0 : _c.value) == null ? void 0 : _d.script, `${path}.defaultParams.value.script`);
  addSource((_f = (_e = step.params) == null ? void 0 : _e.value) == null ? void 0 : _f.script, `${path}.params.value.script`);
}
function collectRunJsSources(spec, path, context) {
  const sources = [];
  const settings = _.isPlainObject(spec.settings) ? spec.settings : void 0;
  const addSource = (code, sourcePath) => {
    if (typeof code === "string" && code.trim()) {
      sources.push({ code, path: sourcePath });
    }
  };
  addSource(settings == null ? void 0 : settings.code, `${path}.settings.code`);
  addSource(settings == null ? void 0 : settings.source, `${path}.settings.source`);
  addSource(spec.code, `${path}.code`);
  addSource(spec.source, `${path}.source`);
  if (context.authoringActionName === "applyBlueprint" && typeof spec.script === "string" && spec.script.trim()) {
    const scriptKey = spec.script.trim();
    const asset = _.isPlainObject(context.applyBlueprintScriptAssets) ? context.applyBlueprintScriptAssets[scriptKey] : void 0;
    if (_.isPlainObject(asset) && typeof asset.code === "string" && asset.code.trim()) {
      sources.push({
        code: asset.code,
        path: `${path}.script`
      });
    }
  }
  return sources;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  collectFlowRegistryRunJsAuthoringErrors,
  collectRunJsAuthoringErrors
});
