"use client";

import Link from "next/link";
import { useState } from "react";
import { ChevronDown, ChevronUp, GripVertical } from "lucide-react";
import { bulkPanelsAction, copyPanelAction, deletePanelAction, reorderPanelsAction } from "@/lib/actions/panels";
import type { PanelLocationOption } from "@/lib/public/panel-positions";
import { cn } from "@/lib/utils";
import { StatusLine, useRun } from "@/components/features/accounts/use-run";
import { Modal, Pill, edInput, pillClass } from "@/components/features/page-editor/ed-ui";

export interface PanelRow { id: string; name: string; position: string; active: boolean; pageCount: number | null }

interface Props {
  siteId: string;
  panels: PanelRow[];
  locations: PanelLocationOption[];
  canManage: boolean;
  /** Super admins can open the locations page from here. */
  /** Add, copy and delete (everyone who can manage panels). */
  canAddDelete: boolean;
  canEditLocations: boolean;
}

const OTHER = "__other";

/** ShowOff-style panel list: collapsible location groups, each panel a card with drag handle, tick box, status and an Edit Panel split button. */
export function PanelsList({ siteId, panels, locations, canManage, canAddDelete, canEditLocations }: Props) {
  const { pending, msg, run } = useRun();
  const [filter, setFilter] = useState<"all" | "active" | "inactive">("all");
  const [closed, setClosed] = useState<string[]>([]);
  const [selected, setSelected] = useState<string[]>([]);
  const [menu, setMenu] = useState<string | null>(null);
  const [confirm, setConfirm] = useState<{ ids: string[]; label: string } | null>(null);
  const [dragId, setDragId] = useState<string | null>(null);
  const [order, setOrder] = useState(panels.map((p) => p.id));
  const byId = new Map(panels.map((p) => [p.id, p]));
  // Local order (after a drag) plus anything new that arrived from the server, e.g. a copy.
  const baseIds = [...order.filter((id) => byId.has(id)), ...panels.map((p) => p.id).filter((id) => !order.includes(id))];
  const ordered = baseIds.map((id) => byId.get(id)).filter((p): p is PanelRow => Boolean(p));
  const known = new Set(locations.map((l) => l.key));
  const groups = [
    ...locations.map((l) => ({ key: l.key, name: l.name, builtIn: l.builtIn, help: l.help })),
    ...(ordered.some((p) => !known.has(p.position)) ? [{ key: OTHER, name: "Unavailable location", builtIn: true, help: "These panels sit in a location this website no longer has access to, so they are not shown on the website. Open one and move it to another location." }] : []),
  ];
  const inGroup = (key: string) => ordered.filter((p) => (key === OTHER ? !known.has(p.position) : p.position === key));
  const visible = (p: PanelRow) => filter === "all" || (filter === "active" ? p.active : !p.active);

  const commit = (next: string[]) => { setOrder(next); run(() => reorderPanelsAction(siteId, next)); };
  const move = (id: string, delta: number) => {
    const p = byId.get(id);
    if (!p) return;
    const group = ordered.filter((x) => x.position === p.position);
    const other = group[group.findIndex((x) => x.id === id) + delta];
    if (!other) return;
    const next = [...baseIds];
    const a = next.indexOf(id);
    const b = next.indexOf(other.id);
    [next[a], next[b]] = [next[b]!, next[a]!];
    commit(next);
  };
  const dropOn = (toId: string) => {
    const from = dragId ? byId.get(dragId) : undefined;
    const to = byId.get(toId);
    setDragId(null);
    if (!from || !to || from.id === to.id || from.position !== to.position) return;
    const next = baseIds.filter((x) => x !== from.id);
    next.splice(next.indexOf(toId) + (baseIds.indexOf(from.id) < baseIds.indexOf(toId) ? 1 : 0), 0, from.id);
    commit(next);
  };

  return (
    <div className="space-y-5">
      <div className="flex flex-wrap items-center gap-3">
        <h1 className="mr-auto text-4xl font-bold tracking-tight text-[var(--ed-ink)]">Panels</h1>
        {canAddDelete ? <Link href="/dashboard/panels/new" className={pillClass("outline", "py-2.5")}>Add Panel</Link> : null}
        <Link href={canEditLocations ? "/dashboard/panel-locations" : "/dashboard/panels/positions"} className={pillClass("outline", "py-2.5")}>Edit Panel Positions</Link>
      </div>
      <div className="flex flex-wrap items-center justify-end gap-3">
        {canManage && selected.length > 0 ? (
          <div role="group" aria-label="Actions for ticked panels" className="mr-auto flex flex-wrap items-center gap-2 rounded-full bg-white px-4 py-2 text-xs font-bold shadow-sm">
            <span>{selected.length} selected</span>
            <Pill variant="green" disabled={pending} onClick={() => run(() => bulkPanelsAction(selected, "activate"), () => setSelected([]))}>Activate</Pill>
            <Pill variant="grey" disabled={pending} onClick={() => run(() => bulkPanelsAction(selected, "deactivate"), () => setSelected([]))}>Deactivate</Pill>
            {canAddDelete ? <Pill variant="pink" disabled={pending} onClick={() => setConfirm({ ids: selected, label: `${selected.length} selected panel${selected.length === 1 ? "" : "s"}` })}>Delete</Pill> : null}
          </div>
        ) : null}
        <label htmlFor="panel-status" className="sr-only">Status</label>
        <select id="panel-status" value={filter} onChange={(e) => setFilter(e.target.value as typeof filter)} className={cn(edInput, "w-44 rounded-xl bg-white")}>
          <option value="all">Any Status</option><option value="active">Active</option><option value="inactive">Inactive</option>
        </select>
      </div>
      <StatusLine msg={msg} />

      <div className="space-y-4">
        {groups.map((g) => {
          const all = inGroup(g.key);
          const shown = all.filter(visible);
          const open = !closed.includes(g.key);
          return (
            <section key={g.key} aria-label={`${g.name} panels`} className="space-y-3">
              <div className="flex items-center gap-3">
                <button type="button" aria-expanded={open} aria-label={`${open ? "Collapse" : "Expand"} ${g.name}`} onClick={() => setClosed(open ? [...closed, g.key] : closed.filter((k) => k !== g.key))} className="inline-flex size-6 items-center justify-center text-[var(--ed-soft)]">
                  {open ? <ChevronUp className="size-4" aria-hidden /> : <ChevronDown className="size-4" aria-hidden />}
                </button>
                <div className="flex min-w-0 flex-1 items-center gap-3 rounded-2xl bg-white px-5 py-4 shadow-sm">
                  <h2 className="min-w-0 truncate text-sm font-bold text-[var(--ed-ink)]">{g.name}</h2>
                  {!g.builtIn ? <span className="rounded-full bg-[var(--ed-grey)] px-2 py-0.5 text-[10px] font-bold text-[var(--ed-ink)]">custom</span> : null}
                  <span className="hidden truncate text-xs text-[var(--ed-soft)] md:block">{g.help}</span>
                  {g.key !== OTHER ? <Link href={canEditLocations && !g.builtIn ? `/dashboard/panel-locations/${g.key}` : `/dashboard/panels/positions/${g.key}`} className={pillClass("grey", "ml-auto shrink-0")}>Edit Position</Link> : null}
                </div>
              </div>
              {open ? (
                shown.length === 0 ? (
                  <p className="ml-9 rounded-2xl bg-white/60 px-5 py-3 text-sm text-[var(--ed-soft)]">{all.length === 0 ? "No panels in this location yet." : "No panels match this status."}</p>
                ) : (
                  <ul className="ml-9 space-y-3" aria-label={`${g.name} panels`}>
                    {shown.map((p) => {
                      const gi = all.findIndex((x) => x.id === p.id);
                      return (
                        <li key={p.id} onDragOver={(e) => { if (dragId) e.preventDefault(); }} onDrop={(e) => { e.preventDefault(); dropOn(p.id); }} className={cn("flex flex-wrap items-center gap-3 rounded-2xl bg-white px-4 py-3 shadow-sm", dragId === p.id && "opacity-50")}>
                          {canManage && g.key !== OTHER ? (
                            <button
                              type="button"
                              draggable
                              aria-label={`Drag ${p.name} to reorder (or press Alt with the up or down arrow)`}
                              onDragStart={(e) => { setDragId(p.id); e.dataTransfer.effectAllowed = "move"; }}
                              onDragEnd={() => setDragId(null)}
                              onKeyDown={(e) => { if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown")) { e.preventDefault(); move(p.id, e.key === "ArrowUp" ? -1 : 1); } }}
                              disabled={pending}
                              className="inline-flex size-10 cursor-grab items-center justify-center rounded-lg bg-[var(--ed-grey)] text-[var(--ed-ink)]"
                            ><GripVertical className="size-4" aria-hidden /></button>
                          ) : null}
                          {canManage ? <input type="checkbox" className="size-5" aria-label={`Select ${p.name}`} checked={selected.includes(p.id)} onChange={(e) => setSelected(e.target.checked ? [...selected, p.id] : selected.filter((x) => x !== p.id))} /> : null}
                          {!p.active ? <span className="rounded-full border-2 border-[var(--ed-dark)] px-3 py-0.5 text-xs font-bold text-[var(--ed-dark)]">Inactive</span> : null}
                          <Link href={`/dashboard/panels/${p.id}`} className="min-w-0 flex-1 truncate text-sm text-[var(--ed-ink)] hover:underline">
                            {p.name}{p.pageCount !== null ? <em className="ml-1 text-[var(--ed-soft)]">(restricted)</em> : null}
                          </Link>
                          <div className="relative inline-flex">
                            <Link href={`/dashboard/panels/${p.id}`} className={pillClass("grey", "rounded-r-none pr-4")}>{canManage ? "Edit Panel" : "View Panel"}</Link>
                            {canManage && canAddDelete ? (
                              <>
                                <button type="button" aria-label={`More actions for ${p.name}`} aria-haspopup="menu" aria-expanded={menu === p.id} onClick={() => setMenu(menu === p.id ? null : p.id)} className={pillClass("grey", "rounded-l-none border-l border-black/10 px-2.5")}><ChevronDown className="size-3.5" aria-hidden /></button>
                                {menu === p.id ? (
                                  <div role="menu" className="absolute right-0 top-full z-20 mt-1 w-40 overflow-hidden rounded-2xl bg-[var(--ed-dark)] text-white shadow-xl" onMouseLeave={() => setMenu(null)} onKeyDown={(e) => { if (e.key === "Escape") setMenu(null); }}>
                                    <button type="button" role="menuitem" disabled={pending} className="block w-full px-4 py-2.5 text-left text-sm font-semibold hover:bg-white/15" onClick={() => { setMenu(null); run(() => copyPanelAction(p.id)); }}>Copy</button>
                                    <button type="button" role="menuitem" disabled={pending} className="block w-full px-4 py-2.5 text-left text-sm font-semibold hover:bg-white/15" onClick={() => { setMenu(null); setConfirm({ ids: [p.id], label: `“${p.name}”` }); }}>Delete</button>
                                  </div>
                                ) : null}
                              </>
                            ) : null}
                          </div>
                          <span className="sr-only">{gi + 1} of {all.length}</span>
                        </li>
                      );
                    })}
                  </ul>
                )
              ) : null}
            </section>
          );
        })}
      </div>

      {confirm ? (
        <Modal title="Delete?" onClose={() => setConfirm(null)}>
          <p className="px-8 pb-2 text-center text-sm text-[var(--ed-ink)]">{confirm.label} will be permanently removed from this website.</p>
          <div className="flex justify-center gap-3 px-6 py-6">
            <Pill variant="pink" className="min-w-32 py-3" disabled={pending} onClick={() => { const ids = confirm.ids; setConfirm(null); run(() => (ids.length === 1 ? deletePanelAction(ids[0]!) : bulkPanelsAction(ids, "delete")), () => setSelected([])); }}>Delete</Pill>
            <Pill variant="grey" className="min-w-32 py-3" onClick={() => setConfirm(null)}>Cancel</Pill>
          </div>
        </Modal>
      ) : null}
    </div>
  );
}
