import type { TenantSummary } from "../../../lib/adminApi";
import { buildTenantFullTree, type TenantNode } from "../../../lib/tenantTree";

export type TenantViewMode = "tree" | "table";
export type TenantViewRow = TenantNode & { depth: number };

export function tenantMatchesListSearch(
  tenant: Pick<TenantSummary, "id" | "name" | "slug" | "type">,
  search: string,
) {
  const normalizedSearch = search.trim().toLowerCase();
  if (!normalizedSearch) return true;

  return [tenant.name, tenant.slug, tenant.id, tenant.type]
    .filter(Boolean)
    .some((value) => value.toLowerCase().includes(normalizedSearch));
}

export function getTenantSearchMatchIds(
  rows: Array<Pick<TenantSummary, "id" | "name" | "slug" | "type">>,
  search: string,
) {
  if (!search.trim()) return [];
  return rows
    .filter((row) => tenantMatchesListSearch(row, search))
    .map((row) => row.id);
}

export function filterTenantViewRowsBySearch<T extends TenantViewRow>(
  rows: T[],
  search: string,
) {
  if (!search.trim()) return rows;
  return rows.filter((row) => tenantMatchesListSearch(row, search));
}

function collectTenantTreeRows(
  nodes: TenantNode[],
  depth: number,
  rows: TenantViewRow[],
) {
  for (const node of nodes) {
    rows.push({ ...node, depth });
    collectTenantTreeRows(node.children, depth + 1, rows);
  }
}

function collectTenantDescendantIds(
  tenantId: string,
  tenants: TenantSummary[],
) {
  const childrenByParent = new Map<string, TenantSummary[]>();
  for (const tenant of tenants) {
    if (!tenant.parentId) continue;
    const children = childrenByParent.get(tenant.parentId) ?? [];
    children.push(tenant);
    childrenByParent.set(tenant.parentId, children);
  }

  const ids: string[] = [];
  const visitedIds = new Set<string>();
  const visit = (parentId: string) => {
    for (const child of childrenByParent.get(parentId) ?? []) {
      if (visitedIds.has(child.id)) continue;
      visitedIds.add(child.id);
      ids.push(child.id);
      visit(child.id);
    }
  };
  visit(tenantId);
  return ids;
}

export function filterTenantsByScope(
  tenants: TenantSummary[],
  scopeTenantId: string,
) {
  if (!scopeTenantId) return tenants;
  const descendantIds = new Set(
    collectTenantDescendantIds(scopeTenantId, tenants),
  );
  return tenants.filter((tenant) => descendantIds.has(tenant.id));
}

export function getTenantViewRows(
  tenants: TenantSummary[],
  viewMode: TenantViewMode,
  scopeTenantId = "",
  isSearchActive = false,
): TenantViewRow[] {
  const { subTree } = buildTenantFullTree(
    tenants,
    scopeTenantId || undefined,
    isSearchActive,
  );
  const treeRows: TenantViewRow[] = [];
  collectTenantTreeRows(subTree, 0, treeRows);

  if (viewMode === "tree") {
    return treeRows;
  }

  const rowsById = new Map(treeRows.map((row) => [row.id, row]));
  const flatSource = scopeTenantId
    ? filterTenantsByScope(tenants, scopeTenantId)
    : tenants;

  return flatSource.map((tenant) => ({
    ...(rowsById.get(tenant.id) ?? {
      ...tenant,
      children: [],
      recursiveMemberCount:
        Number(tenant.totalMemberCount ?? tenant.memberCount) || 0,
    }),
    depth: 0,
  }));
}

export function resolveTenantSelectionIds({
  currentIds,
  tenant,
  checked,
  tenants,
  deletableTenants,
}: {
  currentIds: string[];
  tenant: TenantSummary;
  checked: boolean;
  tenants: TenantSummary[];
  deletableTenants: TenantSummary[];
}) {
  const allowedIds = new Set(deletableTenants.map((item) => item.id));
  const targetIds = [
    tenant.id,
    ...collectTenantDescendantIds(tenant.id, tenants),
  ].filter((id) => allowedIds.has(id));
  const next = new Set(currentIds.filter((id) => allowedIds.has(id)));

  if (checked) {
    for (const id of targetIds) {
      next.add(id);
    }
  } else {
    for (const id of targetIds) {
      next.delete(id);
    }
  }

  return Array.from(next);
}
