import { Organization } from "@open-mercato/core/modules/directory/data/entities";
function normalizeUuid(value) {
  if (!value) return null;
  const v = String(value).trim();
  if (!v || v.toLowerCase() === "null" || v.toLowerCase() === "undefined") return null;
  return v;
}
function computeHierarchyForOrganizations(organizations, tenantId) {
  const nodes = /* @__PURE__ */ new Map();
  for (const org of organizations) {
    const id = String(org.id);
    const node = {
      org,
      parentId: normalizeUuid(org.parentId),
      children: /* @__PURE__ */ new Set()
    };
    nodes.set(id, node);
  }
  for (const [id, node] of nodes) {
    const parentId = node.parentId;
    if (!parentId || parentId === id) {
      node.parentId = null;
      continue;
    }
    const parent = nodes.get(parentId);
    if (!parent) {
      node.parentId = null;
      continue;
    }
    parent.children.add(id);
  }
  const computed = /* @__PURE__ */ new Map();
  const orderedIds = [];
  const orderedSet = /* @__PURE__ */ new Set();
  const visited = /* @__PURE__ */ new Set();
  function walk(nodeId, ancestors) {
    if (ancestors.includes(nodeId)) {
      const orgName = nodes.get(nodeId)?.org.name || "";
      computed.set(nodeId, {
        id: nodeId,
        tenantId,
        name: orgName,
        pathLabel: orgName,
        parentId: null,
        depth: 0,
        rootId: nodeId,
        treePath: nodeId,
        ancestorIds: [],
        childIds: [],
        descendantIds: [],
        isActive: nodes.get(nodeId)?.org.isActive ?? true
      });
      if (!orderedSet.has(nodeId)) {
        orderedIds.push(nodeId);
        orderedSet.add(nodeId);
      }
      visited.add(nodeId);
      return [];
    }
    const node = nodes.get(nodeId);
    if (!node) return [];
    visited.add(nodeId);
    const org = node.org;
    const id = String(org.id);
    const nextAncestors = [...ancestors, id];
    if (!orderedSet.has(id)) {
      orderedIds.push(id);
      orderedSet.add(id);
    }
    const childIds = Array.from(node.children).filter((childId) => nodes.has(childId)).sort((a, b) => {
      const an = nodes.get(a).org.name.toLowerCase();
      const bn = nodes.get(b).org.name.toLowerCase();
      if (an === bn) return a.localeCompare(b);
      return an.localeCompare(b);
    });
    const descendantIds = [];
    for (const childId of childIds) {
      const desc = walk(childId, nextAncestors);
      descendantIds.push(childId, ...desc);
    }
    const ancestorIds = ancestors;
    const depth = ancestorIds.length;
    const rootId = ancestorIds.length ? ancestorIds[0] : id;
    const treePath = nextAncestors.join("/");
    const ancestorNames = ancestors.map((ancestorId) => nodes.get(ancestorId)?.org.name).filter((value) => typeof value === "string" && value.length > 0);
    const pathLabel = [...ancestorNames, org.name].join(" / ");
    const computedNode = {
      id,
      tenantId,
      name: org.name,
      pathLabel,
      parentId: node.parentId,
      depth,
      rootId,
      treePath,
      ancestorIds,
      childIds,
      descendantIds,
      isActive: !!org.isActive
    };
    computed.set(id, computedNode);
    return descendantIds;
  }
  for (const [id, node] of nodes) {
    if (!node.parentId || !nodes.has(node.parentId)) {
      walk(id, []);
    }
  }
  for (const id of nodes.keys()) {
    if (!visited.has(id)) {
      walk(id, []);
    }
  }
  const ordered = orderedIds.map((id) => computed.get(id)).filter((node) => !!node);
  return { map: computed, ordered };
}
async function rebuildHierarchyForTenant(em, tenantId) {
  const organizations = await em.find(Organization, { tenant: tenantId, deletedAt: null }, { orderBy: { name: "ASC" } });
  const hierarchy = computeHierarchyForOrganizations(organizations, tenantId);
  const now = /* @__PURE__ */ new Date();
  for (const org of organizations) {
    const computed = hierarchy.map.get(String(org.id));
    if (!computed) {
      org.parentId = null;
      org.rootId = String(org.id);
      org.treePath = String(org.id);
      org.depth = 0;
      org.ancestorIds = [];
      org.childIds = [];
      org.descendantIds = [];
      org.updatedAt = now;
      continue;
    }
    org.parentId = computed.parentId;
    org.rootId = computed.rootId;
    org.treePath = computed.treePath;
    org.depth = computed.depth;
    org.ancestorIds = computed.ancestorIds;
    org.childIds = computed.childIds;
    org.descendantIds = computed.descendantIds;
    org.updatedAt = now;
  }
  await em.flush();
  return hierarchy;
}
export {
  computeHierarchyForOrganizations,
  rebuildHierarchyForTenant
};
//# sourceMappingURL=hierarchy.js.map
