/**
 * The navigation table.
 *
 * Lifted out of Shell.tsx because four things now read it — the sidebar, the
 * phone tab bar, the command palette and the header's page title — and a table
 * that four consumers each filter differently is a table that ends up
 * duplicated.
 *
 * Visibility is a *capability* question, not a cosmetic one. The convention in
 * this codebase is to disable a control rather than hide it, so that the
 * interface tells you the same story regardless of who you are. Navigation is
 * the exception: a destination someone cannot use is not a disabled control,
 * it is a page that answers 403, and offering it is worse than omitting it.
 */
import {
  Boxes,
  Building2,
  CalendarClock,
  FileSpreadsheet,
  FileText,
  GraduationCap,
  LayoutDashboard,
  MessageCircleMore,
  Server,
  Settings,
  ShieldCheck,
  Target,
  TrendingUp,
  Users,
  type LucideIcon,
} from 'lucide-react';
import type { Capability, Team } from '@pig/core';
import { canAny, type PermissionIdentity } from './permissions';

export const NAV_GROUPS = ['Intelligence', 'Marketplace', 'Records', 'Control'] as const;
export type NavGroup = (typeof NAV_GROUPS)[number];

export interface NavItem {
  to: string;
  label: string;
  icon: LucideIcon;
  shortcut?: string;
  group: NavGroup;
  /** Shown in the phone tab bar. Space there is scarce, so only five fit. */
  primary?: boolean;
  /**
   * Hide the item unless this capability is granted somewhere. Absent means
   * the page is readable by any member — which includes Settings, where the
   * appearance controls and Sign out live for everybody, admin or not.
   */
  requires?: Capability;
  /** Narrows `requires` to one team, where the API enforces one. */
  requiresTeam?: Team;
}

export const NAV: NavItem[] = [
  { to: '/', label: 'Overview', icon: LayoutDashboard, group: 'Intelligence', primary: true },
  { to: '/growth', label: 'Growth', icon: Target, group: 'Intelligence' },
  { to: '/calendar', label: 'Calendar', icon: CalendarClock, group: 'Intelligence' },
  { to: '/piggy', label: 'Piggy', icon: MessageCircleMore, group: 'Intelligence' },
  { to: '/learn', label: 'Learn', icon: GraduationCap, group: 'Intelligence' },
  { to: '/margin', label: 'Margin', icon: TrendingUp, group: 'Intelligence', primary: true },
  { to: '/capacity', label: 'Capacity', icon: Server, group: 'Marketplace', primary: true },
  { to: '/demand', label: 'Demand', icon: Building2, group: 'Marketplace', primary: true },
  { to: '/supply', label: 'Supply', icon: Boxes, group: 'Marketplace', primary: true },
  { to: '/accounts', label: 'Accounts', icon: Building2, group: 'Records' },
  { to: '/contracts', label: 'Contracts', icon: FileText, group: 'Records' },
  {
    to: '/imports',
    label: 'Import',
    icon: FileSpreadsheet,
    group: 'Records',
    requires: 'data:import',
  },
  { to: '/team', label: 'Team', icon: Users, group: 'Control' },
  {
    to: '/facts',
    label: 'Fact review',
    icon: ShieldCheck,
    group: 'Control',
    // The API gates fact review on data:import for the research team
    // specifically (routes/facts.ts), so the nav has to ask the same question.
    requires: 'data:import',
    requiresTeam: 'research',
  },
  { to: '/settings', label: 'Settings', icon: Settings, group: 'Control' },
];

export function visibleNav(identity: PermissionIdentity | undefined): NavItem[] {
  return NAV.filter((item) => {
    if (!item.requires) return true;
    if (!item.requiresTeam) return canAny(identity, item.requires);
    return Boolean(
      identity &&
        identity.permissions.some(
          (grant) =>
            grant.capability === item.requires &&
            (grant.team === null || grant.team === item.requiresTeam),
        ),
    );
  });
}

/** The nav entry a pathname belongs to, for the header title and active state. */
export function activeNavItem(items: readonly NavItem[], pathname: string): NavItem | undefined {
  return items.find((item) =>
    item.to === '/' ? pathname === '/' : pathname === item.to || pathname.startsWith(`${item.to}/`),
  );
}
