/**
 * 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 locator_exports = {};
__export(locator_exports, {
  SurfaceLocator: () => SurfaceLocator
});
module.exports = __toCommonJS(locator_exports);
var import_lodash = __toESM(require("lodash"));
var import_approval = require("./approval");
var import_chart_config = require("./chart-config");
var import_errors = require("./errors");
class SurfaceLocator {
  constructor(db, repository) {
    this.db = db;
    this.repository = repository;
  }
  async resolve(target, options = {}) {
    var _a, _b;
    const transaction = options.transaction;
    if (target.uid) {
      return this.resolveByUid(target.uid, target, transaction);
    }
    if ("tabSchemaUid" in target && target.tabSchemaUid) {
      return this.resolveByUid(target.tabSchemaUid, target, transaction);
    }
    if ("pageSchemaUid" in target && target.pageSchemaUid) {
      return this.resolvePageSchemaUid(target.pageSchemaUid, target, transaction);
    }
    if ("routeId" in target && target.routeId) {
      const route = await this.db.getRepository("desktopRoutes").findOne({
        filterByTk: String(target.routeId),
        transaction
      });
      if (isPageRoute(route)) {
        return this.resolvePageSchemaUid(route.get("schemaUid"), target, transaction);
      }
      if (((_a = route == null ? void 0 : route.get) == null ? void 0 : _a.call(route, "type")) === "group") {
        throw new import_errors.FlowSurfaceBadRequestError(
          `flowSurfaces routeId '${target.routeId}' points to a menu group, not a page surface. Menu group routeIds can be used directly as navigation.group.routeId; do not use flowSurfaces:get to check whether a menu group exists.`,
          void 0,
          {
            ruleId: "route-id-points-to-menu-group",
            details: {
              routeId: String(target.routeId),
              title: route.get("title") ?? null,
              type: "group"
            }
          }
        );
      }
      if ((_b = route == null ? void 0 : route.get) == null ? void 0 : _b.call(route, "schemaUid")) {
        return this.resolveByUid(route.get("schemaUid"), target, transaction);
      }
    }
    throw new import_errors.FlowSurfaceBadRequestError("flowSurfaces target not found");
  }
  async findParentUid(uid, transaction) {
    var _a;
    const parentPath = await this.db.getRepository("flowModelTreePath").findOne({
      filter: {
        descendant: uid,
        depth: 1
      },
      transaction
    });
    return ((_a = parentPath == null ? void 0 : parentPath.get) == null ? void 0 : _a.call(parentPath, "ancestor")) || null;
  }
  async findRouteBySchemaUid(schemaUid, transaction) {
    return this.db.getRepository("desktopRoutes").findOne({
      filter: {
        schemaUid
      },
      transaction
    });
  }
  async resolveCollectionContext(uid, transaction) {
    let cursor = uid;
    while (cursor) {
      const model = await this.repository.findModelById(cursor, { transaction, includeAsyncNode: true });
      const resourceInit = import_lodash.default.get(model, ["stepParams", "resourceSettings", "init"]) || import_lodash.default.get(model, ["stepParams", "TriggerChildPageSettings", "init"]) || import_lodash.default.get(model, ["stepParams", "ApprovalChildPageSettings", "init"]) || ((model == null ? void 0 : model.use) === "ChartBlockModel" ? (0, import_chart_config.getChartBuilderResourceInit)(import_lodash.default.get(model, ["stepParams", "chartSettings", "configure"])) : null);
      if ((resourceInit == null ? void 0 : resourceInit.dataSourceKey) && (resourceInit == null ? void 0 : resourceInit.collectionName)) {
        return {
          ownerUid: cursor,
          model,
          resourceInit
        };
      }
      const fieldInit = import_lodash.default.get(model, ["stepParams", "fieldSettings", "init"]);
      if ((fieldInit == null ? void 0 : fieldInit.dataSourceKey) && (fieldInit == null ? void 0 : fieldInit.collectionName)) {
        return {
          ownerUid: cursor,
          model,
          resourceInit: {
            dataSourceKey: fieldInit.dataSourceKey,
            collectionName: fieldInit.collectionName,
            associationPathName: fieldInit.associationPathName
          }
        };
      }
      cursor = await this.findParentUid(cursor, transaction);
    }
    return null;
  }
  async resolveByUid(uid, target, transaction) {
    var _a, _b, _c, _d, _e;
    const node = await this.repository.findModelById(uid, { transaction, includeAsyncNode: true });
    const route = await this.findRouteBySchemaUid(uid, transaction);
    if (!(node == null ? void 0 : node.uid) && !route) {
      throw new import_errors.FlowSurfaceBadRequestError(`flowSurfaces uid '${uid}' not found`);
    }
    let pageRoute = null;
    let tabRoute = null;
    if (((_a = route == null ? void 0 : route.get) == null ? void 0 : _a.call(route, "type")) === "tabs") {
      tabRoute = route;
      pageRoute = route.get("parentId") ? await this.db.getRepository("desktopRoutes").findOne({
        filterByTk: String(route.get("parentId")),
        transaction
      }) : null;
    } else if (((_b = route == null ? void 0 : route.get) == null ? void 0 : _b.call(route, "type")) === "flowPage" || ((_c = route == null ? void 0 : route.get) == null ? void 0 : _c.call(route, "type")) === "page") {
      pageRoute = route;
    } else if (node == null ? void 0 : node.uid) {
      pageRoute = await this.findPageRouteFromModel(node.uid, transaction).catch(() => {
        return null;
      }) || null;
      tabRoute = await this.findRouteBySchemaUid(node.uid, transaction);
      if (((_d = tabRoute == null ? void 0 : tabRoute.get) == null ? void 0 : _d.call(tabRoute, "type")) !== "tabs") {
        tabRoute = null;
      }
    }
    return {
      target,
      uid: (node == null ? void 0 : node.uid) || uid,
      kind: ((_e = tabRoute == null ? void 0 : tabRoute.get) == null ? void 0 : _e.call(tabRoute, "type")) === "tabs" ? "tab" : isPageRoute(pageRoute) ? "page" : inferKind(node == null ? void 0 : node.use),
      node,
      route,
      pageRoute,
      tabRoute
    };
  }
  async resolvePageSchemaUid(pageSchemaUid, target, transaction) {
    var _a;
    const pageModel = await this.repository.findModelByParentId(pageSchemaUid, {
      transaction,
      subKey: "page",
      includeAsyncNode: true
    });
    const route = await this.db.getRepository("desktopRoutes").findOne({
      filter: {
        schemaUid: pageSchemaUid
      },
      transaction
    });
    if (pageModel == null ? void 0 : pageModel.uid) {
      return {
        target,
        uid: pageModel.uid,
        kind: "page",
        node: pageModel,
        route,
        pageRoute: route,
        pageModel
      };
    }
    if ((_a = route == null ? void 0 : route.get) == null ? void 0 : _a.call(route, "schemaUid")) {
      return {
        target,
        uid: route.get("schemaUid"),
        kind: "page",
        route,
        pageRoute: route,
        pageModel
      };
    }
    throw new import_errors.FlowSurfaceBadRequestError("flowSurfaces target not found");
  }
  async findPageRouteFromModel(uid, transaction) {
    var _a, _b;
    let cursor = uid;
    while (cursor) {
      const route = await this.findRouteBySchemaUid(cursor, transaction);
      if (((_a = route == null ? void 0 : route.get) == null ? void 0 : _a.call(route, "type")) === "flowPage" || ((_b = route == null ? void 0 : route.get) == null ? void 0 : _b.call(route, "type")) === "page") {
        return route;
      }
      const parentUid = await this.findParentUid(cursor, transaction);
      if (!parentUid) {
        return null;
      }
      cursor = parentUid;
    }
    return null;
  }
}
function inferKind(use) {
  const normalized = (0, import_approval.normalizeApprovalSemanticUse)(use);
  if (normalized === "RouteModel") {
    return "node";
  }
  if (normalized === "RootPageModel" || normalized === "ChildPageModel") {
    return "page";
  }
  if (normalized === "RootPageTabModel" || normalized === "ChildPageTabModel") {
    return "tab";
  }
  if (/GridModel$/.test(normalized || "")) {
    return "grid";
  }
  if (/BlockModel$/.test(normalized || "")) {
    return "block";
  }
  return "node";
}
function isPageRoute(route) {
  var _a;
  const type = ((_a = route == null ? void 0 : route.get) == null ? void 0 : _a.call(route, "type")) || (route == null ? void 0 : route.type);
  return type === "flowPage" || type === "page";
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  SurfaceLocator
});
