"use client";

import { useQueryClient } from "@tanstack/react-query";
import {
  Bell,
  CalendarClock,
  ClipboardList,
  Gauge,
  HandCoins,
  LayoutDashboard,
  LineChart,
  Map,
  MapPin,
  MessageSquareText,
  Package,
  PackageSearch,
  PlusSquare,
  ShieldCheck,
  SlidersHorizontal,
  Store,
  Truck,
  Webhook,
  UserCog,
  Users,
  Zap,
} from "lucide-react";
import { useCan } from "@/features/auth/use-can";
import { useT } from "@/i18n";
import { queryKeys } from "@/lib/query-keys";
import { getNotifications } from "@/services/notifications";
import { BELL_PREVIEW_ROWS } from "@/features/notifications/notification-bell";
import { getAwaitingCollection, getOrders } from "@/services/orders";
import { getDrivers } from "@/services/drivers";
import { getVehicles } from "@/services/vehicles";
import { getDashboardStats } from "@/services/stats";
import { getPushStats } from "@/services/push";
import { getStoreClients } from "@/services/store-clients";

export interface NavItem {
  href: string;
  label: string;
  icon: React.ComponentType<{ className?: string }>;
  visible: () => boolean;
  exact?: boolean;
  prefetch?: () => void;
}

/**
 * A parent in the sidebar: a name, an icon, and the links that belong under it.
 *
 * **Grouped rather than listed**, because twenty links in one column is a list somebody reads from
 * the top every time instead of navigating. The grouping is by the thing being worked on — orders,
 * captains, money — not by which permission opens it, since that is how the person at the desk
 * thinks about their own job.
 *
 * `flat` marks a group of one that should read as a link rather than as a folder: Overview and
 * Support are destinations, and wrapping either in a chevron would be a folder with nothing to open.
 */
export interface NavGroup {
  /** Stable across renders and translations: the sidebar remembers what is open by this. */
  key: string;
  label: string;
  icon: React.ComponentType<{ className?: string }>;
  items: NavItem[];
  flat?: boolean;
}

export type NavKind = "operations" | "administration";

/**
 * Single source of truth for the dashboard menu. Both the sidebar and the ⌘K
 * command palette read from here, so navigation and permissions never drift.
 * `prefetch` warms the exact TanStack Query key each destination page uses.
 */
export function useNavItems(): NavGroup[] {
  const t = useT();
  const { can } = useCan();
  const queryClient = useQueryClient();

  const prefetch = (href: string) => {
    switch (href) {
      case "/overview": {
        void queryClient.prefetchQuery({
          queryKey: queryKeys.stats,
          queryFn: async () => (await getDashboardStats()).Model ?? null,
        });
        break;
      }
      case "/orders": {
        const filters = { page: 1, rows: 10 };
        void queryClient.prefetchQuery({
          queryKey: queryKeys.orders.list(filters),
          queryFn: () => getOrders(filters),
        });
        break;
      }
      case "/orders/awaiting-collection": {
        void queryClient.prefetchQuery({
          queryKey: queryKeys.orders.awaitingCollection(1),
          queryFn: () => getAwaitingCollection(),
        });
        break;
      }
      case "/captains": {
        const filters = { page: 1, rows: 10 };
        void queryClient.prefetchQuery({
          queryKey: queryKeys.drivers.list(filters),
          queryFn: () => getDrivers(filters),
        });
        break;
      }
      case "/applications": {
        const filters = { page: 1, rows: 25, status: "pending" as const };
        void queryClient.prefetchQuery({
          queryKey: queryKeys.drivers.list(filters),
          queryFn: () => getDrivers(filters),
        });
        break;
      }
      case "/vehicles": {
        const filters = { page: 1, rows: 10 };
        void queryClient.prefetchQuery({
          queryKey: queryKeys.vehicles.list(filters),
          queryFn: () => getVehicles(filters),
        });
        break;
      }
      case "/notifications": {
        // The bell's preview window — the dropdown and the page share this cache key.
        const filters = { page: 1, rows: BELL_PREVIEW_ROWS };
        void queryClient.prefetchQuery({
          queryKey: queryKeys.notifications.list(filters),
          queryFn: () => getNotifications(filters),
        });
        break;
      }
      case "/stores": {
        const filters = { page: 1, rows: 10 };
        void queryClient.prefetchQuery({
          queryKey: queryKeys.storeClients.list(filters),
          queryFn: () => getStoreClients(filters),
        });
        break;
      }
      case "/push": {
        void queryClient.prefetchQuery({
          queryKey: queryKeys.push.stats,
          queryFn: async () => (await getPushStats()).Model ?? null,
        });
        break;
      }
    }
  };

  /*
   * The order of the groups is the order of a shift: what is happening now, the work itself, the
   * people doing it, then the money and the records behind it. Administration sits last because
   * nobody starts their day there.
   */
  return [
    {
      key: "overview",
      label: t("nav.overview"),
      icon: LayoutDashboard,
      flat: true,
      items: [
        {
          href: "/overview",
          label: t("nav.overview"),
          icon: LayoutDashboard,
          visible: () => true,
          exact: true,
          prefetch: () => prefetch("/overview"),
        },
      ],
    },
    {
      key: "orders",
      label: t("nav.group.orders"),
      icon: Package,
      items: [
        {
          href: "/orders",
          label: t("nav.orders"),
          icon: Package,
          visible: () => can(["orders.view", "orders.create", "orders.assign"]),
          prefetch: () => prefetch("/orders"),
        },
        {
          /*
           * Its own entry rather than a filter on the orders list: these orders are `pending` like
           * any other, so there is no status to filter by — what blocks them is a fact about a
           * different row, and nothing else on the screen would show it.
           */
          href: "/orders/awaiting-collection",
          label: t("nav.awaitingCollection"),
          icon: PackageSearch,
          visible: () => can("orders.view"),
          prefetch: () => prefetch("/orders/awaiting-collection"),
        },
        {
          href: "/orders/new",
          label: t("nav.newOrder"),
          icon: PlusSquare,
          visible: () => can("orders.create"),
        },
      ],
    },
    {
      key: "fleet",
      label: t("nav.group.fleet"),
      icon: Users,
      items: [
        {
          href: "/captains",
          label: t("nav.captains"),
          icon: Users,
          visible: () => can(["drivers.view", "drivers.update", "drivers.review"]),
          prefetch: () => prefetch("/captains"),
        },
        {
          href: "/applications",
          label: t("nav.applications"),
          icon: ClipboardList,
          visible: () => can("drivers.review"),
          prefetch: () => prefetch("/applications"),
        },
        {
          href: "/vehicles",
          label: t("nav.vehicles"),
          icon: Truck,
          visible: () => can(["vehicles.view", "vehicles.create", "vehicles.update"]),
          prefetch: () => prefetch("/vehicles"),
        },
        {
          href: "/attendance",
          label: t("nav.attendance"),
          icon: CalendarClock,
          visible: () => can("drivers.view"),
        },
      ],
    },
    {
      key: "live",
      label: t("nav.group.live"),
      icon: MapPin,
      items: [
        {
          href: "/tracking",
          label: t("nav.tracking"),
          icon: MapPin,
          visible: () => can("drivers.view"),
        },
        {
          href: "/performance",
          label: t("nav.performance"),
          icon: LineChart,
          // The dispatch counters, not the order list: this is the permission the KPI endpoint
          // itself checks, so the link never leads to a screen that answers 403.
          visible: () => can("dispatch.view"),
        },
      ],
    },
    {
      key: "money",
      label: t("nav.group.money"),
      icon: HandCoins,
      items: [
        {
          href: "/payments",
          label: t("nav.payments"),
          icon: HandCoins,
          // The cash desk, not the orders list: an admin who may read orders has no business
          // seeing what each captain owes, and one who runs the desk may not need orders at all.
          visible: () => can("captain_ledger.view"),
        },
        {
          href: "/cities",
          label: t("nav.cities"),
          icon: Map,
          // The areas and what they pay, not the cash desk: somebody who prices a district does not
          // thereby get to see what every captain owes.
          visible: () => can("cities.view"),
        },
      ],
    },
    {
      key: "stores",
      label: t("nav.group.stores"),
      icon: Store,
      items: [
        {
          href: "/stores",
          label: t("nav.stores"),
          icon: Store,
          visible: () => can(["store_clients.view", "store_clients.review", "store_clients.manage"]),
          prefetch: () => prefetch("/stores"),
        },
        {
          href: "/integration",
          label: t("nav.integration"),
          icon: Webhook,
          visible: () => can(["integration.view", "integration.replay"]),
        },
      ],
    },
    {
      key: "messaging",
      label: t("nav.group.messaging"),
      icon: Bell,
      items: [
        {
          href: "/notifications",
          label: t("nav.notifications"),
          icon: Bell,
          visible: () => can("notifications.view"),
          prefetch: () => prefetch("/notifications"),
        },
        {
          href: "/push",
          label: t("nav.push"),
          icon: Zap,
          visible: () => can("push.view"),
          prefetch: () => prefetch("/push"),
        },
      ],
    },
    {
      key: "administration",
      label: t("nav.administration"),
      icon: SlidersHorizontal,
      items: [
        {
          href: "/settings",
          label: t("nav.myProfile"),
          icon: Gauge,
          visible: () => true,
          exact: true,
        },
        {
          href: "/settings/admins",
          label: t("nav.admins"),
          icon: UserCog,
          visible: () => can(["admins.view", "admins.create", "admins.update"]),
        },
        {
          href: "/settings/roles",
          label: t("nav.roles"),
          icon: ShieldCheck,
          visible: () => can(["roles.view", "roles.create", "roles.update"]),
        },
        {
          href: "/settings/dispatch",
          label: t("nav.dispatchSettings"),
          icon: SlidersHorizontal,
          // Reading the dials is enough to be shown the page; changing one is checked on the screen,
          // and again by the server.
          visible: () => can("dispatch.view"),
        },
      ],
    },
    {
      key: "support",
      label: t("nav.support"),
      icon: MessageSquareText,
      flat: true,
      items: [
        {
          href: "/support",
          label: t("nav.support"),
          icon: MessageSquareText,
          visible: () => true,
        },
      ],
    },
  ];
}
