import type { NavItem, NavSection } from './AppSidebar';

/** Both shapes are accepted so callers can migrate to sections gradually. */
export type NavEntries = NavItem[] | NavSection[];

export function toSections(entries: NavEntries): NavSection[] {
  if (entries.length === 0) return [];
  const isSectioned = (entries as NavSection[])[0]?.items !== undefined;
  return isSectioned
    ? (entries as NavSection[])
    : [{ items: entries as NavItem[] }];
}

/**
 * Whether a nav entry points at the current route.
 *
 * Prefix-matches on a path boundary so `/licensing` lights up for
 * `/licensing/FREIGHT_FORWARDER` but not for an unrelated `/licensing-report`.
 */
export function isItemActive(item: NavItem, activePath: string): boolean {
  if (!item.to) return false;
  return activePath === item.to || activePath.startsWith(`${item.to}/`);
}

/** True when the item, or anything nested under it, matches the route. */
export function isBranchActive(item: NavItem, activePath: string): boolean {
  if (isItemActive(item, activePath)) return true;
  return (item.children ?? []).some((child) => isItemActive(child, activePath));
}

/**
 * Removes entries the user may not see.
 *
 * An item with no `permissions` is visible to everyone. A parent survives if
 * it is itself permitted and at least one child is — a disclosure that opens
 * onto nothing is worse than no disclosure at all. Sections left empty are
 * dropped so their heading does not hang over a gap.
 */
export function filterByPermissions(
  sections: NavSection[],
  granted: readonly string[],
): NavSection[] {
  const permitted = new Set(granted);
  const allows = (item: NavItem) =>
    !item.permissions?.length ||
    item.permissions.some((permission) => permitted.has(permission));

  return sections
    .map((section) => ({
      ...section,
      items: section.items
        .filter(allows)
        .map((item) =>
          item.children
            ? { ...item, children: item.children.filter(allows) }
            : item,
        )
        .filter((item) => !item.children || item.children.length > 0),
    }))
    .filter((section) => section.items.length > 0);
}

/** Flattens parents and children into one list, for search and breadcrumbs. */
export function flattenNav(sections: NavSection[]): NavItem[] {
  return sections.flatMap((section) =>
    section.items.flatMap((item) => [item, ...(item.children ?? [])]),
  );
}

/** Badge text, or null when there is nothing worth showing. */
export function badgeLabel(badge: NavItem['badge']): string | null {
  if (badge === 'dot') return '';
  if (typeof badge === 'number' && badge > 0) {
    // Three digits of pending work is already "a lot"; the exact number
    // stops being actionable and starts breaking the layout.
    return badge > 99 ? '99+' : String(badge);
  }
  return null;
}
