import { ChevronDown } from "lucide-react";
import Link from "next/link";
import { notFound } from "next/navigation";
import { AddMenuDialog, MenuItemsEditor, MenuRowActions } from "@/components/features/menus";
import { Card, EmptyState, PageHeader, buttonClass } from "@/components/ui";
import { canAnywhere } from "@/lib/authz/context";
import { requireDashboard } from "@/lib/authz/guard";
import { AuthError } from "@/lib/authz/errors";
import { getActiveSiteId, listAccessibleSites } from "@/lib/data/sites";
import { getMenuEditorData, listAllMenus, listMenus, type MenuRow } from "@/lib/services/navigation";

const th = "px-4 py-3 font-medium";

function MenusTable({ caption, menus, superAdmin }: { caption: string; menus: MenuRow[]; superAdmin: boolean }) {
  if (menus.length === 0) return <EmptyState title="No menus" description="This website has no menus yet." />;
  return (
    <div className="overflow-x-auto" tabIndex={0} role="region" aria-label={caption}>
      <table className="w-full text-left text-sm">
        <caption className="sr-only">{caption}</caption>
        <thead className="border-b border-border text-xs text-muted-foreground"><tr><th scope="col" className={th}>Name</th><th scope="col" className={th}>No. of Menu Items</th><th scope="col" className={th}><span className="sr-only">Actions</span></th></tr></thead>
        <tbody className="divide-y divide-border">
          {menus.map((m) => (
            <tr key={m.id}>
              <th scope="row" className="px-4 py-3 font-medium">{m.name}</th>
              <td className="px-4 py-3">{m.itemCount}</td>
              <td className="px-4 py-3"><div className="flex justify-end"><MenuRowActions menuId={m.id} name={m.name} system={m.system} superAdmin={superAdmin} /></div></td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

/** Org admin / editor view: the menus of the website that is open. Super admins also get Add Menu here. */
export async function MenusScreen() {
  const ctx = await requireDashboard("admin");
  if (!canAnywhere(ctx, "navigation.manage")) notFound();
  const siteId = await getActiveSiteId(await listAccessibleSites(ctx));
  if (!siteId) return (<><PageHeader title="Menus" /><Card><EmptyState title="Choose a website" description="Open a website first (Edit in your website list) to see its menus." /></Card></>);
  let data;
  try { data = await listMenus(siteId); } catch (e) { if (e instanceof AuthError) notFound(); throw e; }
  const all = ctx.isSuperAdmin ? await listAllMenus() : [];
  return (
    <>
      <PageHeader title="Menus" description={`${data.site.name} · the menus on this website. Header and footer menus are shown on every page.`} actions={ctx.isSuperAdmin ? <AddMenuDialog sites={all} presetSiteId={siteId} /> : undefined} />
      <Card><MenusTable caption={`Menus of ${data.site.name}`} menus={data.menus} superAdmin={ctx.isSuperAdmin} /></Card>
    </>
  );
}

/** Super admin view: every organisation's websites with their menus, plus Add Menu for any of them. */
export async function AllMenusScreen({ q }: { q: string }) {
  await requireDashboard("super-admin");
  const groups = await listAllMenus();
  const needle = q.trim().toLowerCase();
  const shown = needle ? groups.filter((g) => `${g.siteName} ${g.organizationName}`.toLowerCase().includes(needle) || g.menus.some((m) => m.name.toLowerCase().includes(needle))) : groups;
  return (
    <>
      <PageHeader title="Menus" description="Add menus to any organisation and website, and edit their items. Organisation admins then manage the items of the menus on their own websites." actions={<AddMenuDialog sites={groups} />} />
      <form method="get" role="search" className="mb-4 flex max-w-sm gap-2">
        <label htmlFor="menu-q" className="sr-only">Search organisations, websites and menus</label>
        <input id="menu-q" name="q" defaultValue={q} placeholder="Search…" className="h-9 w-full rounded-md border border-border bg-card px-3 text-sm" />
        <button type="submit" className={buttonClass("secondary")}>Search</button>
      </form>
      {shown.length === 0 ? <Card><EmptyState title="Nothing found" description={needle ? "No organisation, website or menu matches your search." : "There are no websites yet."} /></Card> : (
        <div className="space-y-4">
          {shown.map((g) => (
            <Card key={g.siteId} className="overflow-hidden">
              <details open={Boolean(needle) || shown.length === 1} className="group">
                <summary className="flex cursor-pointer list-none items-center gap-3 px-4 py-3 text-sm font-semibold hover:bg-muted/50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary [&::-webkit-details-marker]:hidden">
                  <ChevronDown className="h-4 w-4 shrink-0 transition-transform group-open:rotate-180" aria-hidden="true" />
                  <span>{g.siteName}<span className="ml-2 font-normal text-muted-foreground">· {g.organizationName}</span></span>
                  <span className="ml-auto text-xs font-normal text-muted-foreground">{g.menus.length} {g.menus.length === 1 ? "menu" : "menus"}</span>
                </summary>
                <div className="border-t border-border"><MenusTable caption={`Menus of ${g.siteName}`} menus={g.menus} superAdmin /></div>
              </details>
            </Card>
          ))}
        </div>
      )}
    </>
  );
}

export async function MenuEditorScreen({ menuId, kind }: { menuId: string; kind: "admin" | "super-admin" }) {
  await requireDashboard(kind);
  let data;
  try { data = await getMenuEditorData(menuId); } catch (e) { if (e instanceof AuthError) notFound(); throw e; }
  const signature = JSON.stringify(data.items);
  return (
    <>
      <PageHeader title={data.menu.name} description={`${data.site.name} · ${data.site.organization}${data.menu.system ? " · built-in menu shown on every page of the website" : ""}`} actions={<Link href="/dashboard/menus" className={buttonClass("secondary")}>All menus</Link>} />
      <MenuItemsEditor key={signature} menuId={data.menu.id} menuName={data.menu.name} initial={data.items} pages={data.pages} />
    </>
  );
}
