import { ReferenceKind } from "@mikro-orm/core";
let cachedGraph = null;
function mapReferenceKind(kind, mappedBy) {
  switch (kind) {
    case ReferenceKind.MANY_TO_ONE:
      return "BELONGS_TO";
    case ReferenceKind.ONE_TO_MANY:
      return "HAS_MANY";
    case ReferenceKind.ONE_TO_ONE:
      return mappedBy ? "BELONGS_TO_ONE" : "HAS_ONE";
    case ReferenceKind.MANY_TO_MANY:
      return mappedBy ? "BELONGS_TO_MANY" : "HAS_MANY_MANY";
    default:
      return "BELONGS_TO";
  }
}
function getSimpleTypeName(type) {
  if (!type) return "unknown";
  if (typeof type === "function") return type.name || "unknown";
  return type;
}
async function extractEntityGraph(orm) {
  const metadata = orm.getMetadata();
  const allMetadata = metadata.getAll();
  const nodes = [];
  const edges = [];
  for (const [, entityMeta] of Object.entries(allMetadata)) {
    if (entityMeta.abstract || entityMeta.embeddable) continue;
    if (entityMeta.className.startsWith("MikroORM")) continue;
    const properties = [];
    for (const prop of entityMeta.props) {
      if (prop.name.startsWith("_")) continue;
      if (prop.kind !== void 0 && prop.kind !== ReferenceKind.SCALAR) {
        const targetEntity = prop.type;
        if (targetEntity && targetEntity !== entityMeta.className) {
          const relationship = mapReferenceKind(prop.kind, prop.mappedBy);
          edges.push({
            source: entityMeta.className,
            relationship,
            target: targetEntity,
            property: prop.name,
            nullable: prop.nullable ?? false
          });
        }
      } else {
        properties.push({
          name: prop.name,
          type: getSimpleTypeName(prop.type),
          nullable: prop.nullable ?? false
        });
      }
    }
    nodes.push({
      className: entityMeta.className,
      tableName: entityMeta.tableName,
      properties
    });
  }
  nodes.sort((a, b) => a.className.localeCompare(b.className));
  edges.sort((a, b) => {
    const sourceCompare = a.source.localeCompare(b.source);
    if (sourceCompare !== 0) return sourceCompare;
    return a.property.localeCompare(b.property);
  });
  return {
    nodes,
    edges,
    generatedAt: (/* @__PURE__ */ new Date()).toISOString()
  };
}
function formatGraphAsTriples(graph) {
  return graph.edges.map((edge) => {
    const nullable = edge.nullable ? "?" : "";
    return `(${edge.source})-[${edge.relationship}${nullable}:${edge.property}]->(${edge.target})`;
  });
}
function cacheEntityGraph(graph) {
  cachedGraph = graph;
}
function getCachedEntityGraph() {
  return cachedGraph;
}
function filterGraphByEntity(graph, entityName) {
  const lowerEntity = entityName.toLowerCase();
  return graph.edges.filter(
    (edge) => edge.source.toLowerCase().includes(lowerEntity) || edge.target.toLowerCase().includes(lowerEntity)
  );
}
function filterGraphByModule(graph, moduleName) {
  const lowerModule = moduleName.toLowerCase();
  const moduleEntities = /* @__PURE__ */ new Set();
  for (const node of graph.nodes) {
    if (node.tableName.startsWith(lowerModule) || node.className.toLowerCase().includes(lowerModule)) {
      moduleEntities.add(node.className);
    }
  }
  return graph.edges.filter((edge) => moduleEntities.has(edge.source) || moduleEntities.has(edge.target));
}
function filterGraphByType(graph, type) {
  return graph.edges.filter((edge) => edge.relationship === type);
}
function getEntityFields(graph, entityName) {
  const lowerEntity = entityName.toLowerCase();
  return graph.nodes.find((node) => node.className.toLowerCase() === lowerEntity);
}
function listEntitiesByModule(graph) {
  const byModule = /* @__PURE__ */ new Map();
  for (const node of graph.nodes) {
    const module = inferModuleFromEntity(node.className, node.tableName);
    const existing = byModule.get(module) ?? [];
    existing.push(node.className);
    byModule.set(module, existing);
  }
  return byModule;
}
function inferModuleFromEntity(className, tableName) {
  const tableParts = tableName.split("_");
  if (tableParts.length > 1) {
    return tableParts[0];
  }
  const nameWithoutSuffix = className.replace(/Entity$/, "").replace(/Model$/, "");
  const match = nameWithoutSuffix.match(/^([A-Z][a-z]+)/);
  if (match) {
    const prefix = match[1].toLowerCase();
    const moduleMap = {
      sales: "sales",
      customer: "customers",
      catalog: "catalog",
      product: "catalog",
      order: "sales",
      invoice: "sales",
      quote: "sales",
      auth: "auth",
      user: "auth",
      tenant: "auth",
      organization: "auth",
      workflow: "workflows",
      config: "configs",
      dictionary: "dictionaries",
      entity: "entities",
      search: "search",
      attachment: "attachments",
      audit: "audit_logs",
      api: "api_keys",
      dashboard: "dashboards",
      widget: "widgets",
      feature: "feature_toggles",
      perspective: "perspectives",
      currency: "currencies",
      content: "content",
      onboarding: "onboarding"
    };
    if (moduleMap[prefix]) {
      return moduleMap[prefix];
    }
    return prefix;
  }
  return "core";
}
function getEntityRelationships(graph, entityName) {
  const outgoing = graph.edges.filter(
    (edge) => edge.source.toLowerCase() === entityName.toLowerCase()
  );
  const incoming = graph.edges.filter(
    (edge) => edge.target.toLowerCase() === entityName.toLowerCase() && edge.source.toLowerCase() !== entityName.toLowerCase()
  );
  return { outgoing, incoming };
}
function formatTriple(edge) {
  const nullable = edge.nullable ? "?" : "";
  return `(${edge.source})-[${edge.relationship}${nullable}:${edge.property}]->(${edge.target})`;
}
function getGraphStats(graph) {
  const byModule = listEntitiesByModule(graph);
  return {
    totalEntities: graph.nodes.length,
    totalRelationships: graph.edges.length,
    modules: Array.from(byModule.keys()).sort()
  };
}
export {
  cacheEntityGraph,
  extractEntityGraph,
  filterGraphByEntity,
  filterGraphByModule,
  filterGraphByType,
  formatGraphAsTriples,
  formatTriple,
  getCachedEntityGraph,
  getEntityFields,
  getEntityRelationships,
  getGraphStats,
  inferModuleFromEntity,
  listEntitiesByModule
};
//# sourceMappingURL=entity-graph.js.map
