"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { ChevronDown } from "lucide-react";
import { useTranslations } from "next-intl";
import { Link, usePathname } from "@/i18n/routing";
import { canSeeNavGroup, canSeeNavItem } from "@/lib/auth-permissions";
import {
  NAV_GROUPS,
  NAV_GROUPS_STORAGE_KEY,
  findNavGroupForPath,
  type NavGroupDef,
  type NavGroupId,
  type NavItemDef,
} from "@/lib/sidebar-nav";
import { useAuthStore } from "@/lib/stores/auth.store";
import { cn } from "@/lib/utils";

type OpenGroupsState = Partial<Record<NavGroupId, boolean>>;

function readStoredOpenGroups(): OpenGroupsState {
  if (typeof window === "undefined") return {};
  try {
    const raw = localStorage.getItem(NAV_GROUPS_STORAGE_KEY);
    if (!raw) return {};
    return JSON.parse(raw) as OpenGroupsState;
  } catch {
    return {};
  }
}

function buildDefaultOpenGroups(): OpenGroupsState {
  const stored = readStoredOpenGroups();
  const defaults: OpenGroupsState = {};
  for (const g of NAV_GROUPS) {
    defaults[g.id] = stored[g.id] ?? g.defaultOpen;
  }
  return defaults;
}

function persistOpenGroups(next: OpenGroupsState): void {
  try {
    localStorage.setItem(NAV_GROUPS_STORAGE_KEY, JSON.stringify(next));
  } catch {
    /* ignore quota */
  }
}

function NavLink({
  item,
  label,
  active,
}: {
  item: NavItemDef;
  label: string;
  active: boolean;
}) {
  const Icon = item.icon;
  return (
    <Link
      href={item.href}
      className={cn(
        "group flex items-center rounded-lg px-3 py-2 text-sm transition-colors cursor-pointer",
        active
          ? "bg-accent text-accent-foreground font-medium"
          : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"
      )}
    >
      <Icon
        className={cn(
          "h-4 w-4 shrink-0 me-2.5",
          active ? "text-primary" : "text-muted-foreground group-hover:text-foreground"
        )}
      />
      <span className="min-w-0 truncate">{label}</span>
    </Link>
  );
}

function NavGroupSection({
  group,
  title,
  open,
  onToggle,
  pathname,
  role,
  branchId,
  tItem,
}: {
  group: NavGroupDef;
  title: string;
  open: boolean;
  onToggle: () => void;
  pathname: string;
  role: string | undefined;
  branchId: string | null | undefined;
  tItem: (key: string) => string;
}) {
  const visibleItems = group.items.filter((item) =>
    canSeeNavItem(item.key, role, branchId)
  );
  if (visibleItems.length === 0) return null;

  return (
    <div className="mb-1">
      <button
        type="button"
        onClick={onToggle}
        aria-expanded={open}
        className="flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-start transition-colors hover:bg-accent/50 cursor-pointer"
      >
        <ChevronDown
          className={cn(
            "h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform duration-200",
            open && "rotate-180"
          )}
          aria-hidden
        />
        <span className="min-w-0 flex-1 truncate text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground/70">
          {title}
        </span>
      </button>
      <div
        className={cn(
          "grid transition-[grid-template-rows] duration-200",
          open ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
        )}
      >
        <div className="overflow-hidden">
          <div className="space-y-0.5 pb-1 pt-0.5">
            {visibleItems.map((item) => {
              const active =
                pathname === item.href || pathname.startsWith(`${item.href}/`);
              return (
                <NavLink
                  key={item.key}
                  item={item}
                  label={tItem(item.key)}
                  active={active}
                />
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}

export function Sidebar({ side }: { side: "left" | "right" }) {
  const t = useTranslations("nav");
  const tGroups = useTranslations("nav.groups");
  const tBrand = useTranslations("brand");
  const pathname = usePathname();
  const user = useAuthStore((s) => s.user);
  const hasHydrated = useAuthStore((s) => s._hasHydrated);
  const role = user?.role;
  const branchId = user?.branchId ?? null;

  const [openGroups, setOpenGroups] = useState<OpenGroupsState>(buildDefaultOpenGroups);

  const visibleGroups = useMemo(
    () =>
      NAV_GROUPS.filter((g) => {
        if (!canSeeNavGroup(g.id, role, branchId)) return false;
        return g.items.some((item) => canSeeNavItem(item.key, role, branchId));
      }),
    [role, branchId]
  );

  const setGroupOpen = useCallback((groupId: NavGroupId, open: boolean) => {
    setOpenGroups((prev) => {
      const next = { ...prev, [groupId]: open };
      persistOpenGroups(next);
      return next;
    });
  }, []);

  useEffect(() => {
    const activeGroup = findNavGroupForPath(pathname);
    if (!activeGroup) return;
    setOpenGroups((prev) => {
      if (prev[activeGroup]) return prev;
      const next = { ...prev, [activeGroup]: true };
      persistOpenGroups(next);
      return next;
    });
  }, [pathname]);

  return (
    <aside
      className={cn(
        "flex w-56 shrink-0 flex-col bg-background",
        "border-border",
        side === "right" ? "border-s" : "border-e"
      )}
    >
      {/* Logo */}
      <div className="flex h-14 items-center gap-2.5 px-4 border-b border-border">
        <div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-primary/10">
          <svg viewBox="0 0 24 24" className="h-4 w-4 fill-primary" aria-hidden>
            <path d="M3 6h18v2H3V6zm2 4h14v2H5v-2zm-2 4h18v2H3v-2zm4 4h10v2H7v-2z" />
          </svg>
        </div>
        <span className="text-sm font-bold tracking-tight text-foreground">
          {tBrand("name")}
        </span>
      </div>

      {/* Nav */}
      <nav
        className="flex-1 overflow-y-auto p-3 space-y-1
          [&::-webkit-scrollbar]:w-1
          [&::-webkit-scrollbar-track]:bg-transparent
          [&::-webkit-scrollbar-thumb]:rounded-full
          [&::-webkit-scrollbar-thumb]:bg-border"
        aria-label={t("aria")}
      >
        {!hasHydrated ? (
          /* Skeleton — shown for ~50ms until Zustand rehydrates from localStorage.
             Prevents the flash where all groups are briefly visible before
             permission-based filtering kicks in for branch-scoped accounts. */
          <div className="space-y-3 px-1 pt-1">
            {[40, 32, 40, 32, 40].map((w, i) => (
              <div key={i} className="space-y-1.5">
                <div className="h-2 w-20 animate-pulse rounded bg-muted" />
                {Array.from({ length: i % 2 === 0 ? 3 : 2 }).map((_, j) => (
                  <div
                    key={j}
                    className={`h-8 animate-pulse rounded-lg bg-muted`}
                    style={{ width: `${w + j * 4}%` }}
                  />
                ))}
              </div>
            ))}
          </div>
        ) : (
          visibleGroups.map((group) => {
            const isOpen = openGroups[group.id] ?? group.defaultOpen;
            return (
              <NavGroupSection
                key={group.id}
                group={group}
                title={tGroups(group.id)}
                open={isOpen}
                onToggle={() => setGroupOpen(group.id, !isOpen)}
                pathname={pathname}
                role={role}
                branchId={branchId}
                tItem={(key) => t(key)}
              />
            );
          })
        )}
      </nav>

      {/* Footer — user role badge */}
      {user && (
        <div className="border-t border-border px-4 py-3">
          <div className="flex items-center gap-2">
            <div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary/10">
              <span className="text-[11px] font-semibold text-primary">
                {(user.actor ?? user.role).charAt(0).toUpperCase()}
              </span>
            </div>
            <div className="min-w-0 flex-1">
              <p className="truncate text-xs font-medium text-foreground">
                {user.actor ?? user.userId}
              </p>
              <p className="truncate text-[10px] text-muted-foreground">{user.role}</p>
            </div>
          </div>
        </div>
      )}
    </aside>
  );
}
