"use client";

import Link from "next/link";
import { usePathname } from "next/navigation";
import { ChevronRight } from "lucide-react";
import type { TFunction } from "i18next";
import { useEffect, useMemo, useState, type ReactElement } from "react";
import { useTranslation } from "react-i18next";

import {
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
  SidebarMenuSubButton,
  SidebarMenuSubItem,
  useSidebar,
} from "@/components/ui/sidebar";
import {
  ADMIN_NAV_GROUP_ICON,
  ADMIN_NAV_GROUP_ORDER,
  groupAdminNavItems,
} from "@/lib/admin-nav-groups";
import { adminNavLabel } from "@/lib/admin-nav-label";
import { cn } from "@/lib/utils";
import { resolveAdminNavIcon } from "@/modules/_config/admin-nav-icons";
import { ADMIN_BASE, type AdminNavGroup, type AdminNavItem } from "@/modules/_config/admin-nav";

const NAV_BTN =
  "h-8 gap-2 px-2.5 py-0 text-[13px] leading-snug font-normal text-sidebar-foreground/90 hover:text-sidebar-accent-foreground [&_svg]:size-4";
const NAV_ACTIVE = "data-active:bg-red-600 data-active:text-white data-active:font-medium data-active:shadow-sm";
const SUB_NAV =
  "h-8 min-h-8 gap-2 rounded-sm px-2.5 py-0 text-sm leading-snug font-normal text-sidebar-foreground/90 hover:text-sidebar-accent-foreground data-[size=md]:text-sm data-[size=sm]:text-sm [&>span]:text-sm [&_svg]:size-4";

function isActive(
  pathname: string,
  item: { href: string; activeMatchPrefix?: string; segment?: string },
): boolean {
  const { href, activeMatchPrefix, segment } = item;
  const prefix = activeMatchPrefix ?? href;
  if (prefix === ADMIN_BASE || prefix === `${ADMIN_BASE}/`) {
    return pathname === ADMIN_BASE || pathname === `${ADMIN_BASE}/`;
  }
  if (segment === "settings") {
    return pathname === href;
  }
  return pathname === prefix || pathname.startsWith(`${prefix}/`);
}

function defaultOpenGroups(
  groups: { group: AdminNavGroup; items: AdminNavItem[] }[],
  pathname: string,
): Record<AdminNavGroup, boolean> {
  const open = Object.fromEntries(
    ADMIN_NAV_GROUP_ORDER.map((g) => [g, true]),
  ) as Record<AdminNavGroup, boolean>;

  for (const { group, items } of groups) {
    if (items.some((item) => isActive(pathname, item))) {
      open[group] = true;
    }
  }

  return open;
}

function NavLeaf({
  item,
  pathname,
  t,
}: {
  item: AdminNavItem;
  pathname: string;
  t: TFunction;
}): ReactElement {
  const Icon = resolveAdminNavIcon(item.segment);
  const active = isActive(pathname, item);
  const label = adminNavLabel(item.segment, t, item.label);

  return (
    <SidebarMenuItem>
      <SidebarMenuButton
        size="sm"
        tooltip={label}
        isActive={active}
        render={<Link href={item.href} />}
        className={cn(NAV_BTN, NAV_ACTIVE)}
      >
        <Icon data-icon="inline-start" aria-hidden />
        <span>{label}</span>
      </SidebarMenuButton>
    </SidebarMenuItem>
  );
}

function NavSubLeaf({
  item,
  pathname,
  t,
}: {
  item: AdminNavItem;
  pathname: string;
  t: TFunction;
}): ReactElement {
  const Icon = resolveAdminNavIcon(item.segment);
  const active = isActive(pathname, item);
  const label = adminNavLabel(item.segment, t, item.label);

  return (
    <SidebarMenuSubItem>
      <SidebarMenuSubButton
        size="md"
        isActive={active}
        render={<Link href={item.href} />}
        className={cn(SUB_NAV, NAV_ACTIVE)}
      >
        <Icon aria-hidden />
        <span>{label}</span>
      </SidebarMenuSubButton>
    </SidebarMenuSubItem>
  );
}

function NavCollapsibleGroup({
  group,
  items,
  pathname,
  open,
  onToggle,
  t,
}: {
  group: AdminNavGroup;
  items: AdminNavItem[];
  pathname: string;
  open: boolean;
  onToggle: () => void;
  t: TFunction;
}): ReactElement {
  const GroupIcon = ADMIN_NAV_GROUP_ICON[group];
  const groupLabel = t(`sidebar.group.${group}`, { ns: "common", defaultValue: group });
  const hasActiveChild = items.some((item) => isActive(pathname, item));

  return (
    <SidebarMenuItem>
      <SidebarMenuButton
        size="sm"
        type="button"
        data-open={open ? "" : undefined}
        isActive={hasActiveChild && !open}
        className={cn(NAV_BTN, hasActiveChild && !open && NAV_ACTIVE)}
        onClick={onToggle}
      >
        <GroupIcon aria-hidden />
        <span className="flex-1 truncate">{groupLabel}</span>
        <ChevronRight
          aria-hidden
          className={cn(
            "ml-auto size-4 shrink-0 text-sidebar-foreground/50 transition-transform duration-200",
            open && "rotate-90",
          )}
        />
      </SidebarMenuButton>
      {open ? (
        <SidebarMenuSub className="mx-2 gap-0.5 border-sidebar-border/50 px-1.5 py-0.5">
          {items.map((item) => (
            <NavSubLeaf key={item.segment} item={item} pathname={pathname} t={t} />
          ))}
        </SidebarMenuSub>
      ) : null}
    </SidebarMenuItem>
  );
}

export function AdminSidebarNav({
  items,
}: {
  items: readonly AdminNavItem[];
}): ReactElement {
  const { t } = useTranslation("common");
  const pathname = usePathname();
  const { state } = useSidebar();
  const navGroups = useMemo(() => groupAdminNavItems(items), [items]);
  const flatItems = useMemo(() => navGroups.flatMap((g) => g.items), [navGroups]);

  const [openGroups, setOpenGroups] = useState<Record<AdminNavGroup, boolean>>(() =>
    defaultOpenGroups(navGroups, pathname),
  );

  useEffect(() => {
    setOpenGroups((prev) => {
      const next = { ...prev };
      let changed = false;
      for (const { group, items: groupItems } of navGroups) {
        if (groupItems.some((item) => isActive(pathname, item)) && !next[group]) {
          next[group] = true;
          changed = true;
        }
      }
      return changed ? next : prev;
    });
  }, [pathname, navGroups]);

  if (state === "collapsed") {
    return (
      <SidebarMenu className="gap-0.5 px-1.5 py-1.5">
        {flatItems.map((item) => (
          <NavLeaf key={item.segment} item={item} pathname={pathname} t={t} />
        ))}
      </SidebarMenu>
    );
  }

  const overview = navGroups.find((g) => g.group === "overview");
  const collapsible = navGroups.filter((g) => g.group !== "overview");

  return (
    <SidebarMenu className="gap-0.5 px-1.5 py-1.5">
      {overview?.items.map((item) => (
        <NavLeaf key={item.segment} item={item} pathname={pathname} t={t} />
      ))}
      {collapsible.map(({ group, items: groupItems }) => (
        <NavCollapsibleGroup
          key={group}
          group={group}
          items={groupItems}
          pathname={pathname}
          open={openGroups[group] ?? true}
          onToggle={() =>
            setOpenGroups((prev) => ({
              ...prev,
              [group]: !(prev[group] ?? true),
            }))
          }
          t={t}
        />
      ))}
    </SidebarMenu>
  );
}

export function AdminSidebarNavSkeleton(): ReactElement {
  const { t } = useTranslation("common");
  const widths = ["68%", "74%", "58%", "70%", "62%"] as const;

  return (
    <SidebarMenu className="gap-0.5 px-1.5 py-1.5 motion-safe:opacity-90">
      <SidebarMenuItem>
        <div aria-hidden className="flex h-8 items-center gap-2 rounded-md px-2.5">
          <span className="size-4 rounded-sm bg-white/12 motion-safe:animate-pulse" />
          <span className="h-2.5 w-14 rounded-full bg-white/12 motion-safe:animate-pulse" />
        </div>
      </SidebarMenuItem>
      {widths.map((width, i) => (
        <SidebarMenuItem key={i}>
          <div aria-hidden className="flex h-8 items-center gap-2 rounded-md px-2.5">
            <span
              className="size-4 rounded-sm bg-white/12 motion-safe:animate-pulse"
              style={{ animationDelay: `${i * 55}ms` }}
            />
            <span
              className="h-2 rounded-full bg-white/12 motion-safe:animate-pulse"
              style={{ width, animationDelay: `${i * 55 + 40}ms` }}
            />
            <span className="ml-auto size-3 rounded-sm bg-white/10 motion-safe:animate-pulse" />
          </div>
        </SidebarMenuItem>
      ))}
      <span className="sr-only">{t("auth.checking")}</span>
    </SidebarMenu>
  );
}
