"use client";

import clsx from "clsx";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { Suspense, useEffect, useState, type ReactNode } from "react";
import {
  Bot,
  Building2,
  ChevronsUpDown,
  CreditCard,
  Gauge,
  Handshake,
  IndianRupee,
  Layers,
  Scale,
  ScrollText,
  SlidersHorizontal,
  Tags,
  Contact as ContactIcon,
  FileText,
  LayoutDashboard,
  ListChecks,
  LogOut,
  Megaphone,
  Menu,
  MessagesSquare,
  Settings,
  Shapes,
  Users,
  Wallet,
  Workflow,
  X,
  Activity,
  BarChart3,
  Code2,
  LifeBuoy,
  ShieldCheck,
  Building,
} from "lucide-react";
import { Brand } from "./brand";
import { NotificationBell } from "./notification-bell";
import { SessionProvider, useSession } from "./session";
import { api } from "@/lib/api";
import { initials, ROLE_LABELS } from "@/lib/format";
import { useToast } from "./ui/toast";

type NavItem = { href: string; label: string; icon: ReactNode; permission?: string; unless?: string; phase?: number };

const NAV: { heading: string; items: NavItem[] }[] = [
  { heading: "Overview", items: [{ href: "/dashboard", label: "Dashboard", icon: <LayoutDashboard />, permission: "dashboard.view" }] },
  {
    heading: "Audience",
    items: [
      { href: "/contacts", label: "Contacts", icon: <ContactIcon />, permission: "contacts.view" },
      { href: "/contacts/groups", label: "Groups", icon: <Shapes />, permission: "contacts.view" },
      { href: "/contacts/custom-fields", label: "Custom fields", icon: <ListChecks />, permission: "contacts.view" },
    ],
  },
  {
    heading: "Messaging",
    items: [
      { href: "/inbox", label: "Inbox", icon: <MessagesSquare />, permission: "inbox.view" },
      { href: "/templates", label: "Templates", icon: <FileText />, permission: "templates.view" },
      { href: "/campaigns", label: "Campaigns", icon: <Megaphone />, permission: "campaigns.view" },
    ],
  },
  {
    heading: "Automation",
    items: [
      { href: "/bot-replies", label: "Bot replies", icon: <Bot />, permission: "bots.view" },
      { href: "/bot-flows", label: "Bot flows", icon: <Workflow />, permission: "bots.view" },
    ],
  },
  {
    heading: "Insights",
    items: [{ href: "/analytics", label: "Analytics", icon: <BarChart3 />, permission: "analytics.view" }],
  },
  {
    heading: "Account",
    items: [
      { href: "/team", label: "Team", icon: <Users />, permission: "team.view", unless: "reseller.view" },
      { href: "/billing", label: "Wallet & plan", icon: <Wallet />, permission: "billing.view" },
      { href: "/settings/whatsapp", label: "WhatsApp setup", icon: <Settings />, permission: "whatsapp.view" },
      { href: "/settings/workspace", label: "Workspace", icon: <Building />, permission: "workspace.manage" },
      { href: "/developers", label: "Developers", icon: <Code2 />, permission: "developers.view" },
      { href: "/support", label: "Support", icon: <LifeBuoy />, permission: "support.view" },
    ],
  },
  {
    heading: "Reseller",
    items: [
      { href: "/reseller", label: "Overview", icon: <LayoutDashboard />, permission: "reseller.view" },
      { href: "/reseller/customers", label: "Customers", icon: <Building2 />, permission: "reseller.view" },
      { href: "/reseller/plans", label: "Plan prices", icon: <Tags />, permission: "reseller.view" },
      { href: "/reseller/earnings", label: "Earnings", icon: <IndianRupee />, permission: "reseller.view" },
      { href: "/team", label: "Team", icon: <Users />, permission: "reseller.view" },
    ],
  },
  {
    heading: "Platform",
    items: [
      { href: "/admin", label: "Platform overview", icon: <Gauge />, permission: "platform.organizations.view" },
      { href: "/admin/customers", label: "Customers", icon: <Building2 />, permission: "platform.organizations.view" },
      { href: "/admin/resellers", label: "Resellers", icon: <Handshake />, permission: "platform.organizations.view" },
      { href: "/admin/plans", label: "Plans", icon: <Layers />, permission: "platform.organizations.view" },
      { href: "/admin/pricing", label: "Message pricing", icon: <Tags />, permission: "platform.organizations.view" },
      { href: "/admin/payments", label: "Payments", icon: <CreditCard />, permission: "platform.billing.view" },
      { href: "/admin/reconciliation", label: "Reconciliation", icon: <Scale />, permission: "platform.billing.view" },
      { href: "/admin/settings", label: "Billing settings", icon: <SlidersHorizontal />, permission: "platform.settings.manage" },
      { href: "/admin/tickets", label: "Support tickets", icon: <LifeBuoy />, permission: "platform.support.view" },
      { href: "/admin/health", label: "System health", icon: <Activity />, permission: "platform.health.view" },
      { href: "/admin/audit", label: "Audit log", icon: <ScrollText />, permission: "platform.organizations.view" },
    ],
  },
];

function isActive(pathname: string, href: string) {
  if (href === "/contacts" || href === "/admin" || href === "/reseller") return pathname === href;
  return pathname === href || pathname.startsWith(href + "/");
}

/**
 * The pathname is request data on routes with dynamic params, so the active-link state
 * streams in behind Suspense; the fallback is the same nav with nothing highlighted.
 */
function Sidebar({ onNavigate }: { onNavigate?: () => void }) {
  return (
    <Suspense fallback={<SidebarNav pathname="" onNavigate={onNavigate} />}>
      <ActiveSidebar onNavigate={onNavigate} />
    </Suspense>
  );
}

function ActiveSidebar({ onNavigate }: { onNavigate?: () => void }) {
  return <SidebarNav pathname={usePathname()} onNavigate={onNavigate} />;
}

function SidebarNav({ pathname, onNavigate }: { pathname: string; onNavigate?: () => void }) {
  const { can } = useSession();
  return (
    <nav aria-label="Main" className="flex h-full flex-col bg-ink px-3 pb-4 pt-5 text-[14px]">
      <div className="px-2 pb-6">
        <Brand />
      </div>
      <div className="flex-1 space-y-5 overflow-y-auto">
        {NAV.map((section) => {
          const items = section.items.filter((i) => (!i.permission || can(i.permission)) && !(i.unless && can(i.unless)));
          if (!items.length) return null;
          return (
            <div key={section.heading}>
              <h2 className="px-2 pb-1.5 text-xs text-ink-muted/80">{section.heading}</h2>
              <ul className="space-y-0.5">
                {items.map((item) =>
                  item.phase ? (
                    <li key={item.label}>
                      <span
                        className="flex cursor-default items-center gap-3 rounded-md px-2 py-1.5 text-white/35 [&_svg]:size-[18px]"
                        title={`Arrives in phase ${item.phase}`}
                      >
                        {item.icon}
                        <span className="flex-1">{item.label}</span>
                        <span className="rounded bg-white/5 px-1.5 text-[11px] text-white/40">Soon</span>
                      </span>
                    </li>
                  ) : (
                    <li key={item.label}>
                      <Link
                        href={item.href}
                        onClick={onNavigate}
                        aria-current={isActive(pathname, item.href) ? "page" : undefined}
                        className={clsx(
                          "flex items-center gap-3 rounded-md px-2 py-1.5 transition-colors [&_svg]:size-[18px]",
                          isActive(pathname, item.href) ? "bg-white/10 font-medium text-white [&_svg]:text-mint" : "text-white/75 hover:bg-white/5 hover:text-white",
                        )}
                      >
                        {item.icon}
                        {item.label}
                      </Link>
                    </li>
                  ),
                )}
              </ul>
            </div>
          );
        })}
      </div>
    </nav>
  );
}

function OrgSwitcher() {
  const { me, refresh } = useSession();
  const toast = useToast();
  const router = useRouter();
  if (!me?.organization) return null;
  if (me.organizations.length < 2) {
    return <div className="truncate text-sm font-medium text-ink">{me.organization.name}</div>;
  }
  return (
    <label className="relative flex items-center gap-1 text-sm font-medium text-ink">
      <span className="sr-only">Organization</span>
      <select
        value={me.organization.id}
        onChange={async (e) => {
          try {
            await api.post("/auth/switch-organization", { organization_id: Number(e.target.value) });
            await refresh();
            router.refresh();
            toast("success", "Switched organization");
          } catch (err) {
            toast("error", (err as Error).message);
          }
        }}
        className="appearance-none rounded-md bg-transparent py-1 pl-0 pr-6 hover:text-teal focus:outline-none"
      >
        {me.organizations.map((o) => (
          <option key={o.id} value={o.id}>
            {o.name}
          </option>
        ))}
      </select>
      <ChevronsUpDown className="pointer-events-none absolute right-0 size-4 text-muted" />
    </label>
  );
}

function UserMenu() {
  const { me } = useSession();
  const router = useRouter();
  const [open, setOpen] = useState(false);
  if (!me) return <div className="size-9 rounded-full bg-line" />;
  return (
    <div className="relative">
      <button onClick={() => setOpen((o) => !o)} aria-expanded={open} className="flex items-center gap-2.5 rounded-full py-1 pl-1 pr-2 hover:bg-paper">
        <span className="grid size-8 place-items-center rounded-full bg-teal text-xs font-semibold text-white">{initials(me.user.name)}</span>
        <span className="hidden text-left leading-tight sm:block">
          <span className="block text-sm font-medium">{me.user.name}</span>
          <span className="block text-xs text-muted">{ROLE_LABELS[me.role ?? ""] ?? "Member"}</span>
        </span>
      </button>
      {open && (
        <>
          <div className="fixed inset-0 z-30" onClick={() => setOpen(false)} />
          <div className="absolute right-0 z-40 mt-2 w-56 rounded-lg border border-line bg-white p-1 shadow-lg">
            <div className="border-b border-line px-3 py-2 text-xs text-muted">{me.user.email}</div>
            <Link href="/account/security" onClick={() => setOpen(false)} className="flex w-full items-center gap-2 rounded px-3 py-2 text-sm hover:bg-paper">
              <ShieldCheck className="size-4" /> Account security
            </Link>
            <button
              onClick={async () => {
                await api.post("/auth/logout");
                router.replace("/login");
              }}
              className="flex w-full items-center gap-2 rounded px-3 py-2 text-sm hover:bg-paper"
            >
              <LogOut className="size-4" /> Sign out
            </button>
          </div>
        </>
      )}
    </div>
  );
}

/** Staff who must turn on two-step sign-in are sent to Account security until they do. */
function TwoFactorGate() {
  const { me } = useSession();
  const pathname = usePathname();
  const router = useRouter();
  const required = Boolean(me?.security?.two_factor_setup_required);
  useEffect(() => {
    if (required && pathname !== "/account/security") router.replace("/account/security");
  }, [required, pathname, router]);
  if (!required) return null;
  return (
    <div role="status" className="border-b border-amber/30 bg-amber-soft px-4 py-2.5 text-sm text-amber sm:px-6">
      Turn on two-step sign-in to continue. It is required for Devwebs staff accounts.
    </div>
  );
}

function Shell({ children }: { children: ReactNode }) {
  const [mobileOpen, setMobileOpen] = useState(false);
  const { me } = useSession();

  return (
    <div className="min-h-dvh lg:grid lg:grid-cols-[248px_1fr]">
      <aside className="sticky top-0 hidden h-dvh lg:block">
        <Sidebar />
      </aside>
      {mobileOpen && (
        <div className="fixed inset-0 z-50 lg:hidden">
          <div className="absolute inset-0 bg-ink/50" onClick={() => setMobileOpen(false)} />
          <div className="drawer-in absolute inset-y-0 left-0 w-[264px]">
            <Sidebar onNavigate={() => setMobileOpen(false)} />
            <button onClick={() => setMobileOpen(false)} aria-label="Close menu" className="absolute right-3 top-5 text-white/70">
              <X className="size-5" />
            </button>
          </div>
        </div>
      )}
      <div className="flex min-w-0 flex-col">
        <header className="sticky top-0 z-20 flex h-16 items-center gap-3 border-b border-line bg-white/90 px-4 backdrop-blur sm:px-6">
          <button onClick={() => setMobileOpen(true)} aria-label="Open menu" className="-ml-1 rounded p-1.5 text-muted hover:bg-paper lg:hidden">
            <Menu className="size-5" />
          </button>
          <div className="min-w-0 flex-1">
            <OrgSwitcher />
          </div>
          {me?.organization && <NotificationBell />}
          <UserMenu />
        </header>
        <Suspense>
          <TwoFactorGate />
        </Suspense>
        {/* Pages use the reading-width layout; a page whose root has .full-bleed (the inbox) fills the area. */}
        <main className="mx-auto min-h-0 w-full max-w-[1280px] flex-1 px-4 py-6 sm:px-6 lg:px-8 lg:py-8 has-[>.full-bleed]:max-w-none has-[>.full-bleed]:p-0">{children}</main>
      </div>
    </div>
  );
}

export function AppShell({ children }: { children: ReactNode }) {
  return (
    <SessionProvider>
      <Shell>{children}</Shell>
    </SessionProvider>
  );
}
