'use client';

import { useEffect, useState } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import {
  ArrowLeft,
  CalendarDays,
  FileText,
  Gift,
  Home,
  LayoutDashboard,
  Menu,
  Receipt,
  Shield,
  UserRound,
  Users,
  X,
  type LucideIcon,
} from 'lucide-react';
import { Logo } from '@/components/ui/Logo';
import { useMessages } from '@/i18n/client';
import { cn } from '@/lib/cn';
import { LanguageSwitcher } from './LanguageSwitcher';
import { UserMenu, type SessionUser } from './UserMenu';

const ICONS = {
  home: Home,
  dashboard: LayoutDashboard,
  reports: FileText,
  sessions: CalendarDays,
  users: Users,
  orders: Receipt,
  affiliate: Gift,
  profile: UserRound,
  admin: Shield,
} satisfies Record<string, LucideIcon>;

export type NavIcon = keyof typeof ICONS;

export interface ShellNavItem {
  href: string;
  label: string;
  icon: NavIcon;
  /** Exact match only (for index routes like /akun that prefix every other item). */
  exact?: boolean;
  /** Extra prefixes that also mark this item active. */
  match?: string[];
}

export interface ShellNavGroup {
  label: string;
  items: ShellNavItem[];
}

/**
 * Signed-in layout for /akun and /admin: a sticky sidebar on desktop and a
 * slide-in drawer on mobile, with the page title area left to each page.
 */
export function DashboardShell({
  user,
  groups,
  area,
  children,
}: {
  user: SessionUser;
  groups: ShellNavGroup[];
  /** Small label under the logo, e.g. "Admin". */
  area?: string;
  children: React.ReactNode;
}) {
  const pathname = usePathname();
  const t = useMessages().dash.shell;
  const [open, setOpen] = useState(false);

  // Close the drawer after navigating.
  const [lastPath, setLastPath] = useState(pathname);
  if (lastPath !== pathname) {
    setLastPath(pathname);
    setOpen(false);
  }

  useEffect(() => {
    if (!open) return;
    const onKey = (e: KeyboardEvent) => e.key === 'Escape' && setOpen(false);
    document.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [open]);

  const isActive = (item: ShellNavItem) =>
    item.exact
      ? pathname === item.href
      : [item.href, ...(item.match ?? [])].some((p) => pathname === p || pathname.startsWith(`${p}/`));

  const nav = (
    <nav aria-label={t.sidebar} className="flex flex-1 flex-col gap-6 overflow-y-auto px-3 py-5">
      {groups.map((g) => (
        <div key={g.label}>
          <p className="px-3 pb-2 text-[11px] font-semibold tracking-[0.12em] text-subtle uppercase">{g.label}</p>
          <ul className="space-y-0.5">
            {g.items.map((item) => {
              const Icon = ICONS[item.icon];
              const active = isActive(item);
              return (
                <li key={item.href}>
                  <Link
                    href={item.href}
                    aria-current={active ? 'page' : undefined}
                    className={cn(
                      'group flex items-center gap-3 rounded-xl px-3 py-2.5 text-[14px] font-medium transition-colors',
                      active ? 'bg-ink text-white shadow-card' : 'text-ink-soft hover:bg-surface hover:text-ink',
                    )}
                  >
                    <Icon
                      className={cn('size-[18px] shrink-0', active ? 'text-white' : 'text-subtle group-hover:text-ink')}
                      aria-hidden
                    />
                    {item.label}
                  </Link>
                </li>
              );
            })}
          </ul>
        </div>
      ))}
    </nav>
  );

  const footer = (
    <div className="border-t border-line p-4">
      <LanguageSwitcher tone="dark" />
      <Link
        href="/"
        className="mt-3 flex items-center gap-2 rounded-xl px-3 py-2 text-[13px] font-medium text-muted transition-colors hover:bg-surface hover:text-ink"
      >
        <ArrowLeft className="size-4" aria-hidden />
        {t.backToSite}
      </Link>
    </div>
  );

  const brand = (
    <div className="flex items-center gap-2.5">
      <Logo tone="dark" />
      {area && (
        <span className="rounded-full bg-accent-soft px-2 py-0.5 text-[10px] font-semibold tracking-wide text-accent uppercase">
          {area}
        </span>
      )}
    </div>
  );

  return (
    <div className="min-h-dvh bg-canvas lg:grid lg:grid-cols-[256px_minmax(0,1fr)]">
      {/* Desktop sidebar */}
      <aside className="sticky top-0 hidden h-dvh flex-col border-r border-line/80 bg-canvas lg:flex print:hidden">
        <div className="flex h-16 items-center px-6">{brand}</div>
        {nav}
        {footer}
      </aside>

      <div className="min-w-0">
        {/* Top bar */}
        <header className="sticky top-0 z-30 border-b border-line/80 bg-canvas/85 backdrop-blur-xl backdrop-saturate-150 print:hidden">
          <div className="flex h-16 items-center justify-between gap-4 px-4 sm:px-8">
            <div className="flex items-center gap-2 lg:hidden">
              <button
                type="button"
                onClick={() => setOpen(true)}
                aria-label={t.menu}
                aria-expanded={open}
                className="-ml-1 inline-flex size-10 items-center justify-center rounded-full text-ink transition-colors hover:bg-surface"
              >
                <Menu className="size-5" aria-hidden />
              </button>
              {brand}
            </div>
            <div className="hidden lg:block" />
            <UserMenu user={user} tone="dark" />
          </div>
        </header>

        <main>{children}</main>
      </div>

      {/* Mobile drawer */}
      <div className={cn('fixed inset-0 z-50 lg:hidden', open ? 'pointer-events-auto' : 'pointer-events-none')} aria-hidden={!open}>
        <div
          onClick={() => setOpen(false)}
          className={cn('absolute inset-0 bg-night-950/40 backdrop-blur-sm transition-opacity', open ? 'opacity-100' : 'opacity-0')}
        />
        <aside
          className={cn(
            'absolute inset-y-0 left-0 flex w-[min(300px,86vw)] flex-col bg-canvas transition-transform duration-300 ease-out-expo',
            open ? 'translate-x-0 shadow-float' : 'invisible -translate-x-full',
          )}
          {...(!open && { inert: true })}
        >
          <div className="flex h-16 items-center justify-between px-5">
            {brand}
            <button
              type="button"
              onClick={() => setOpen(false)}
              aria-label={t.close}
              className="inline-flex size-10 items-center justify-center rounded-full text-ink transition-colors hover:bg-surface"
            >
              <X className="size-5" aria-hidden />
            </button>
          </div>
          {nav}
          {footer}
        </aside>
      </div>
    </div>
  );
}
