"use client";
import { buttonClass } from "@/components/ui/button";

import { useRef, useState } from "react";
import { Button } from "@/components/ui";
import { Field, inputClass } from "@/components/ui/form";
import { Modal } from "@/components/features/library/modal";
import { StatusLine, useRun } from "@/components/features/accounts/use-run";
import { deleteMenuItemAction, reorderMenuItemsAction, saveMenuItemAction } from "@/lib/actions/navigation";
import { ITEM_KINDS, KIND_LABELS, MAX_NAV_ITEMS, STYLE_PRESETS } from "@/lib/navigation/schema";
import type { MenuItemRow } from "@/lib/services/navigation";

interface PageOption { id: string; title: string; slug: string; status: string }
interface Draft { id?: string; parentId: string | null; label: string; kind: MenuItemRow["kind"]; pageId: string; url: string; openInNewTab: boolean; hidden: boolean; style: string; anchor: string }
const blank = (parentId: string | null): Draft => ({ parentId, label: "", kind: "PAGE", pageId: "", url: "", openInNewTab: false, hidden: false, style: "", anchor: "" });
const fromRow = (r: MenuItemRow): Draft => ({ id: r.id, parentId: r.parentId, label: r.label, kind: r.kind, pageId: r.pageId ?? "", url: r.url, openInNewTab: r.openInNewTab, hidden: r.hidden, style: r.style, anchor: r.anchor });

const menuBtn = "block w-full rounded px-3 py-1.5 text-left text-sm hover:bg-muted disabled:opacity-50";

function ItemDialog({ menuId, draft, pages, onClose }: { menuId: string; draft: Draft | null; pages: PageOption[]; onClose: () => void }) {
  const { pending, msg, errors, run } = useRun();
  const [d, setD] = useState<Draft>(draft ?? blank(null));
  const [showRestrictions, setShowRestrictions] = useState(d.hidden);
  const set = (p: Partial<Draft>) => setD((x) => ({ ...x, ...p }));
  const e = (f: string) => errors[`item.${f}`];
  const submit = () => run(() => saveMenuItemAction({ menuId, id: d.id, parentId: d.parentId, item: { label: d.label, kind: d.kind, pageId: d.kind === "PAGE" ? d.pageId || null : null, url: d.url, openInNewTab: d.openInNewTab, hidden: d.hidden, style: d.style, anchor: d.anchor } }), onClose);
  return (
    <form onSubmit={(ev) => { ev.preventDefault(); submit(); }} className="space-y-4">
      <Field id="mi-label" label="Title" error={e("label")}><input id="mi-label" value={d.label} maxLength={80} onChange={(ev) => set({ label: ev.target.value })} className={inputClass} aria-invalid={e("label") ? true : undefined} /></Field>
      <div className="grid gap-4 sm:grid-cols-2">
        <Field id="mi-kind" label="Type"><select id="mi-kind" value={d.kind} onChange={(ev) => set({ kind: ev.target.value as Draft["kind"], url: "" })} className={inputClass}>{ITEM_KINDS.map((k) => <option key={k} value={k}>{KIND_LABELS[k]}</option>)}</select></Field>
        <Field id="mi-style" label="Style"><select id="mi-style" value={d.style} onChange={(ev) => set({ style: ev.target.value })} className={inputClass} aria-invalid={e("style") ? true : undefined}>{STYLE_PRESETS.map((s) => <option key={s.value} value={s.value}>{s.label}</option>)}</select></Field>
      </div>
      {d.kind === "PAGE" ? (
        <Field id="mi-page" label="Content" error={e("pageId")}>
          <select id="mi-page" value={d.pageId} onChange={(ev) => set({ pageId: ev.target.value })} className={inputClass} aria-invalid={e("pageId") ? true : undefined}>
            <option value="">Choose a page…</option>
            {pages.map((p) => <option key={p.id} value={p.id}>{p.title} (/{p.slug === "home" ? "" : p.slug}){p.status !== "PUBLISHED" ? ` — ${p.status.toLowerCase().replace("_", " ")}` : ""}</option>)}
          </select>
        </Field>
      ) : (
        <Field id="mi-url" label={d.kind === "EXTERNAL" ? "Content (web address)" : d.kind === "MAILTO" ? "Content (email address)" : "Content (site path)"} error={e("url")} help={d.kind === "EXTERNAL" ? "Starts with https://" : d.kind === "PATH" ? "Starts with /, e.g. /contact" : undefined}>
          <input id="mi-url" value={d.url} onChange={(ev) => set({ url: ev.target.value })} className={inputClass} aria-invalid={e("url") ? true : undefined} />
        </Field>
      )}
      <div className="grid gap-4 sm:grid-cols-2">
        {d.kind !== "MAILTO" ? <Field id="mi-anchor" label="Page Anchor" error={e("anchor")} help="Optional, jumps to a section, e.g. contact"><input id="mi-anchor" value={d.anchor} maxLength={80} onChange={(ev) => set({ anchor: ev.target.value })} className={inputClass} aria-invalid={e("anchor") ? true : undefined} /></Field> : null}
        <Field id="mi-target" label="Target (where the link opens)"><select id="mi-target" value={d.openInNewTab ? "new" : "same"} onChange={(ev) => set({ openInNewTab: ev.target.value === "new" })} className={inputClass}><option value="same">Same Window</option><option value="new">New Window</option></select></Field>
      </div>
      <div className="rounded-md border border-border">
        <button type="button" aria-expanded={showRestrictions} aria-controls="mi-restrictions" onClick={() => setShowRestrictions((v) => !v)} className="flex w-full items-center justify-between px-3 py-2 text-left text-sm font-medium">Restrictions<span aria-hidden>{showRestrictions ? "▴" : "▾"}</span></button>
        {showRestrictions ? <div id="mi-restrictions" className="border-t border-border px-3 py-3"><label className="flex items-center gap-2 text-sm"><input type="checkbox" checked={d.hidden} onChange={(ev) => set({ hidden: ev.target.checked })} />Hide this item from the website</label></div> : null}
      </div>
      {msg && !msg.ok && Object.keys(errors).length === 0 ? <StatusLine msg={msg} /> : null}
      <div className="flex justify-end gap-3"><Button variant="ghost" onClick={onClose}>Cancel</Button><Button type="submit" disabled={pending}>{pending ? "Saving…" : "Submit"}</Button></div>
    </form>
  );
}

/** ShowOff-style menu editor: draggable rows, Edit split button with Add Child Item / Delete, and an item dialog. */
export function MenuItemsEditor({ menuId, menuName, initial, pages }: { menuId: string; menuName: string; initial: MenuItemRow[]; pages: PageOption[] }) {
  const { pending, msg, run } = useRun();
  const [items, setItems] = useState(initial);
  const [dialog, setDialog] = useState<{ draft: Draft; n: number } | null>(null);
  const [armed, setArmed] = useState<string | null>(null);
  const dragId = useRef<string | null>(null);
  const [over, setOver] = useState<string | null>(null);

  const siblings = (parentId: string | null) => items.filter((i) => i.parentId === parentId);
  const tops = siblings(null);

  function reorder(parentId: string | null, ids: string[]) {
    const byId = new Map(items.map((i) => [i.id, i]));
    const rest = items.filter((i) => i.parentId !== parentId);
    setItems([...rest, ...ids.map((id) => byId.get(id)!)]);
    run(() => reorderMenuItemsAction({ menuId, parentId, orderedIds: ids }));
  }
  function move(it: MenuItemRow, dir: -1 | 1) {
    const ids = siblings(it.parentId).map((s) => s.id);
    const i = ids.indexOf(it.id), j = i + dir;
    if (j < 0 || j >= ids.length) return;
    [ids[i], ids[j]] = [ids[j]!, ids[i]!];
    reorder(it.parentId, ids);
  }
  function drop(target: MenuItemRow) {
    const from = items.find((i) => i.id === dragId.current);
    dragId.current = null; setOver(null);
    if (!from || from.id === target.id || from.parentId !== target.parentId) return;
    const ids = siblings(from.parentId).map((s) => s.id).filter((id) => id !== from.id);
    ids.splice(ids.indexOf(target.id), 0, from.id);
    reorder(from.parentId, ids);
  }
  const open = (draft: Draft) => setDialog((d) => ({ draft, n: (d?.n ?? 0) + 1 }));

  function row(it: MenuItemRow, depth: 0 | 1) {
    const sibs = siblings(it.parentId);
    const idx = sibs.findIndex((s) => s.id === it.id);
    return (
      <li key={it.id} draggable onDragStart={(e) => { e.stopPropagation(); dragId.current = it.id; e.dataTransfer.effectAllowed = "move"; }} onDragOver={(e) => { const f = items.find((i) => i.id === dragId.current); if (f && f.parentId === it.parentId) { e.preventDefault(); setOver(it.id); } }} onDragLeave={() => setOver((o) => (o === it.id ? null : o))} onDrop={(e) => { e.preventDefault(); e.stopPropagation(); drop(it); }} onDragEnd={() => { dragId.current = null; setOver(null); }}>
        <div className={`flex items-center justify-between gap-3 rounded-md border bg-card px-3 py-2 ${over === it.id ? "border-primary" : "border-border"}`}>
          <div className="flex min-w-0 items-center gap-3">
            <span aria-hidden title="Drag to reorder" className="cursor-grab select-none text-muted-foreground">⋮⋮</span>
            <span className="truncate text-sm font-medium">{it.label}</span>
            {it.hidden ? <span className="rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground">Hidden</span> : null}
          </div>
          <div className="inline-flex shrink-0">
            <button type="button" onClick={() => open(fromRow(it))} aria-label={`Edit ${it.label}`} className={buttonClass("grey", "h-8 rounded-r-none px-4")}>Edit</button>
            <details className="relative" onToggle={(e) => { if (!(e.currentTarget as HTMLDetailsElement).open) setArmed(null); }}>
              <summary aria-label={`More actions for ${it.label}`} className={buttonClass("grey", "h-8 w-8 cursor-pointer list-none rounded-l-none border-l border-black/10 px-0")}>▾</summary>
              <div className="absolute right-0 z-10 mt-1 w-44 rounded-md border border-border bg-card p-1 shadow-md">
                {depth === 0 ? <button type="button" className={menuBtn} disabled={items.length >= MAX_NAV_ITEMS} onClick={() => open(blank(it.id))}>Add Child Item</button> : null}
                <button type="button" className={menuBtn} disabled={idx === 0 || pending} onClick={() => move(it, -1)}>Move up</button>
                <button type="button" className={menuBtn} disabled={idx === sibs.length - 1 || pending} onClick={() => move(it, 1)}>Move down</button>
                {armed === it.id ? (
                  <div className="flex gap-1 p-1"><button type="button" className={buttonClass("danger", "h-8 px-3 text-xs")} disabled={pending} onClick={() => { setItems((xs) => xs.filter((x) => x.id !== it.id && x.parentId !== it.id)); run(() => deleteMenuItemAction(menuId, it.id)); }}>Confirm delete</button><button type="button" className="rounded px-2 py-1 text-xs hover:bg-muted" onClick={() => setArmed(null)}>Cancel</button></div>
                ) : <button type="button" className={menuBtn} onClick={() => setArmed(it.id)}>Delete{depth === 0 && siblings(it.id).length ? " (with children)" : ""}</button>}
              </div>
            </details>
          </div>
        </div>
        {depth === 0 && siblings(it.id).length > 0 ? <ol className="mt-2 space-y-2 border-l-2 border-border pl-5">{siblings(it.id).map((c) => row(c, 1))}</ol> : null}
      </li>
    );
  }

  return (
    <>
      <div className="mb-3 flex items-center justify-between gap-3">
        <StatusLine msg={msg} />
        <button type="button" onClick={() => open(blank(null))} disabled={items.length >= MAX_NAV_ITEMS} className={buttonClass("secondary", "ml-auto")}>Add Menu Item</button>
      </div>
      {tops.length === 0 ? <p className="rounded-md border border-dashed border-border p-6 text-center text-sm text-muted-foreground">{menuName} has no items yet. Use Add Menu Item to create the first one.</p> : <ol className="space-y-2" aria-label={`${menuName} items`}>{tops.map((t) => row(t, 0))}</ol>}
      <Modal open={dialog !== null} onClose={() => setDialog(null)} title={dialog?.draft.id ? "Edit Menu Item" : dialog?.draft.parentId ? "Add Child Item" : "Add Menu Item"}>
        {dialog ? <ItemDialog key={dialog.n} menuId={menuId} draft={dialog.draft} pages={pages} onClose={() => setDialog(null)} /> : null}
      </Modal>
    </>
  );
}
