import type { TenantSummary } from "./adminApi";

export type TenantNode = TenantSummary & {
  children: TenantNode[];
  recursiveMemberCount: number;
};

/**
 * Builds a hierarchical tree from a flat list of tenants and calculates
 * direct and recursive member counts for each node.
 */
export function buildTenantFullTree(
  allTenants: TenantSummary[],
  rootId?: string,
): { currentBase: TenantNode | null; subTree: TenantNode[] } {
  if (allTenants.length === 0) return { currentBase: null, subTree: [] };

  const tenantMap = new Map<string, TenantNode>();
  for (const t of allTenants) {
    tenantMap.set(t.id, {
      ...t,
      children: [],
      recursiveMemberCount: t.memberCount || 0,
    });
  }

  // Build initial children relations and prevent simple cycles
  for (const t of allTenants) {
    if (t.parentId && t.parentId !== t.id) {
      const parent = tenantMap.get(t.parentId);
      const child = tenantMap.get(t.id);
      if (parent && child) {
        // Simple cycle prevention during build: don't add if it creates an immediate loop
        parent.children.push(child);
      }
    }
  }

  const visitedForCalc = new Set<string>();
  // Function to calculate recursive counts with cycle protection
  const calculateRecursive = (node: TenantNode): number => {
    if (visitedForCalc.has(node.id)) {
      console.warn(
        `Circular dependency detected in tenant tree for ID: ${node.id}`,
      );
      return 0; // Prevent infinite loop
    }
    visitedForCalc.add(node.id);

    let total = node.memberCount || 0;
    for (const child of node.children) {
      total += calculateRecursive(child);
    }
    node.recursiveMemberCount = total;

    // We don't remove from visitedForCalc here because a tree shouldn't have
    // multiple paths to the same node anyway (it's a tree, not a graph).
    // If it were a DAG, we'd need different logic, but for a tree with parentIds,
    // a node should only be visited once.
    return total;
  };

  // Calculate for all top-level nodes (those without parent or with self-parent)
  for (const node of tenantMap.values()) {
    if (!node.parentId || node.parentId === node.id) {
      visitedForCalc.clear();
      calculateRecursive(node);
    }
  }

  // If a specific rootId is provided, find and return its subtree
  if (rootId) {
    const base = tenantMap.get(rootId);
    if (base) {
      // Re-calculate specifically for our current tenant to be sure if it wasn't a global root
      visitedForCalc.clear();
      calculateRecursive(base);
      return { currentBase: base, subTree: base.children };
    }
    return { currentBase: null, subTree: [] };
  }

  // If no rootId, return all top-level roots as subTree
  const roots = Array.from(tenantMap.values()).filter(
    (n) => !n.parentId || n.parentId === n.id,
  );
  return { currentBase: null, subTree: roots };
}
