"use client";

import { useCallback, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { ConfirmDialog } from "@/components/admin/ConfirmDialog";
import { toast } from "@/components/admin/Toast";
import { StatusBadge } from "@/components/admin/StatusBadge";
import {
  apiPatch,
  apiPost,
  apiDelete,
  FetchError,
  formatDate,
  slugify,
} from "@/lib/client-api";

export interface TemplateModuleMeta {
  id: string;
  slug: string;
  name: string;
  description: string;
  icon: string;
  category: string;
  /** Some modules are implicit (event dates / location) and always included. */
  implicit?: boolean;
}

export interface TemplateAdvanceFolderMeta {
  id: string;
  slug: string;
  name: string;
  description: string;
}

interface TemplateModuleConfig {
  moduleId: string;
  slug: string;
  name: string;
  icon: string;
  category: string;
  isRequired: boolean;
  displayOrder: number;
  enabled: boolean;
  overrides?: { hiddenFields?: string[] };
}

interface TemplateAdvanceFolderConfig {
  folderId: string;
  name: string;
  description: string;
  displayOrder: number;
  enabled: boolean;
}

interface TemplateData {
  id: string;
  name: string;
  slug: string;
  description: string;
  category: string;
  coverImage: string | null;
  hoverImage: string | null;
  hoverCursor: string | null;
  hoverTagline: string | null;
  icon: string;
  status: string;
  displayOrder: number;
  version: number;
  modules: TemplateModuleConfig[];
  advanceFolders: TemplateAdvanceFolderConfig[];
  settings: {
    requireEventDate: boolean;
    requireLocation: boolean;
    allowEndDate: boolean;
    allowMultipleFunctions: boolean;
    allowCustomModules: boolean;
    allowFileUploads: boolean;
    allowCollaboration: boolean;
  };
  createdAt: string;
  updatedAt: string;
}

export function TemplateBuilder({
  templateId,
  initial,
  moduleLibrary,
  advanceFolderLibrary,
}: {
  templateId: string;
  initial: TemplateData;
  moduleLibrary: TemplateModuleMeta[];
  advanceFolderLibrary: TemplateAdvanceFolderMeta[];
}) {
  const router = useRouter();
  const [data, setData] = useState<TemplateData>(initial);
  const [dirty, setDirty] = useState(false);
  const [saving, setSaving] = useState(false);
  const [activeSlug, setActiveSlug] = useState<string | null>(
    initial.modules[0]?.slug ?? null,
  );
  const [showPreview, setShowPreview] = useState(false);
  const [showPublishConfirm, setShowPublishConfirm] = useState(false);

  const markDirty = useCallback(
    (patch: Partial<TemplateData> | ((d: TemplateData) => TemplateData)) => {
      setData((prev) => {
        const next =
          typeof patch === "function"
            ? (patch as (d: TemplateData) => TemplateData)(prev)
            : { ...prev, ...patch };
        setDirty(true);
        return next;
      });
    },
    [],
  );

  const orderedSelected = useMemo(
    () => [...data.modules].sort((a, b) => a.displayOrder - b.displayOrder),
    [data.modules],
  );

  const orderedAdvanceFolders = useMemo(
    () =>
      [...data.advanceFolders].sort(
        (a, b) => a.displayOrder - b.displayOrder,
      ),
    [data.advanceFolders],
  );

  const advanceFolderLibraryById = useMemo(
    () => new Map(advanceFolderLibrary.map((f) => [f.id, f])),
    [advanceFolderLibrary],
  );

  const selectedAdvanceFolderIds = useMemo(
    () => new Set(data.advanceFolders.map((f) => f.folderId)),
    [data.advanceFolders],
  );

  const advanceFolderLibraryAvailable = useMemo(
    () =>
      advanceFolderLibrary.filter(
        (f) => !selectedAdvanceFolderIds.has(f.id),
      ),
    [advanceFolderLibrary, selectedAdvanceFolderIds],
  );

  const libraryBySlug = useMemo(
    () => new Map(moduleLibrary.map((m) => [m.slug, m])),
    [moduleLibrary],
  );

  const selectedSlugs = useMemo(
    () => new Set(data.modules.map((m) => m.slug)),
    [data.modules],
  );

  const libraryAvailable = useMemo(
    () => moduleLibrary.filter((m) => !selectedSlugs.has(m.slug) && !m.implicit),
    [moduleLibrary, selectedSlugs],
  );

  const implicitModules = useMemo(
    () => moduleLibrary.filter((m) => m.implicit),
    [moduleLibrary],
  );

  const activeModule = data.modules.find((m) => m.slug === activeSlug) ?? null;
  const activeMeta = activeSlug ? libraryBySlug.get(activeSlug) ?? null : null;

  const saveDraft = async () => {
    try {
      setSaving(true);
      const payload = {
        name: data.name,
        slug: data.slug,
        description: data.description,
        category: data.category,
        coverImage: data.coverImage,
        hoverImage: data.hoverImage,
        hoverCursor: data.hoverCursor,
        hoverTagline: data.hoverTagline,
        icon: data.icon,
        displayOrder: data.displayOrder,
        modules: orderedSelected.map((m, idx) => ({
          moduleId: m.moduleId,
          isRequired: m.isRequired,
          displayOrder: idx,
          enabled: m.enabled,
          overrides: { hiddenFields: m.overrides?.hiddenFields ?? [] },
        })),
        advanceFolders: orderedAdvanceFolders.map((f, idx) => ({
          folderId: f.folderId,
          displayOrder: idx,
          enabled: f.enabled,
        })),
        settings: data.settings,
      };
      const result = await apiPatch<TemplateData>(
        `/api/admin/templates/${templateId}`,
        payload,
      );
      setData(result);
      setDirty(false);
      toast("Draft saved.", "success");
      router.refresh();
    } catch (err) {
      toast(
        err instanceof FetchError ? err.message : "Failed to save draft.",
        "error",
      );
    } finally {
      setSaving(false);
    }
  };

  const publish = async () => {
    try {
      setSaving(true);
      if (dirty) {
        await saveDraft();
      }
      const result = await apiPost<TemplateData>(
        `/api/admin/templates/${templateId}/publish`,
      );
      setData(result);
      setDirty(false);
      toast("Template published.", "success");
      router.refresh();
    } catch (err) {
      toast(
        err instanceof FetchError ? err.message : "Failed to publish template.",
        "error",
      );
    } finally {
      setSaving(false);
      setShowPublishConfirm(false);
    }
  };

  const unpublish = async () => {
    try {
      setSaving(true);
      const result = await apiDelete<TemplateData>(
        `/api/admin/templates/${templateId}/publish`,
      );
      setData(result);
      toast("Template unpublished.", "info");
      router.refresh();
    } catch (err) {
      toast(
        err instanceof FetchError ? err.message : "Failed to unpublish template.",
        "error",
      );
    } finally {
      setSaving(false);
    }
  };

  const duplicate = async () => {
    try {
      setSaving(true);
      const created = await apiPost<TemplateData>(
        `/api/admin/templates/${templateId}/duplicate`,
      );
      toast("Template duplicated.", "success");
      router.push(`/admin/templates/${created.id}/edit`);
    } catch (err) {
      toast(
        err instanceof FetchError ? err.message : "Failed to duplicate.",
        "error",
      );
    } finally {
      setSaving(false);
    }
  };

  const archive = async () => {
    try {
      setSaving(true);
      await apiPost(`/api/admin/templates/${templateId}/archive`);
      toast("Template archived.", "info");
      router.refresh();
    } catch (err) {
      toast(
        err instanceof FetchError ? err.message : "Failed to archive.",
        "error",
      );
    } finally {
      setSaving(false);
    }
  };

  const addModule = (mod: TemplateModuleMeta) => {
    markDirty((d) => ({
      ...d,
      modules: [
        ...d.modules,
        {
          moduleId: mod.id,
          slug: mod.slug,
          name: mod.name,
          icon: mod.icon,
          category: mod.category,
          isRequired: false,
          displayOrder: d.modules.length,
          enabled: true,
          overrides: { hiddenFields: [] },
        },
      ],
    }));
    setActiveSlug(mod.slug);
  };

  const removeModule = (slug: string) => {
    markDirty((d) => ({
      ...d,
      modules: d.modules.filter((m) => m.slug !== slug),
    }));
    if (activeSlug === slug) setActiveSlug(null);
  };

  const moveModule = (slug: string, dir: -1 | 1) => {
    markDirty((d) => {
      const sorted = [...d.modules].sort(
        (a, b) => a.displayOrder - b.displayOrder,
      );
      const idx = sorted.findIndex((m) => m.slug === slug);
      const swap = idx + dir;
      if (idx < 0 || swap < 0 || swap >= sorted.length) return d;
      const tmp = sorted[idx].displayOrder;
      sorted[idx].displayOrder = sorted[swap].displayOrder;
      sorted[swap].displayOrder = tmp;
      return { ...d, modules: sorted };
    });
  };

  const toggleRequired = (slug: string) => {
    markDirty((d) => ({
      ...d,
      modules: d.modules.map((m) =>
        m.slug === slug ? { ...m, isRequired: !m.isRequired } : m,
      ),
    }));
  };

  const toggleEnabled = (slug: string) => {
    markDirty((d) => ({
      ...d,
      modules: d.modules.map((m) =>
        m.slug === slug ? { ...m, enabled: !m.enabled } : m,
      ),
    }));
  };

  const addAdvanceFolder = (folder: TemplateAdvanceFolderMeta) => {
    markDirty((d) => ({
      ...d,
      advanceFolders: [
        ...d.advanceFolders,
        {
          folderId: folder.id,
          name: folder.name,
          description: folder.description,
          displayOrder: d.advanceFolders.length,
          enabled: true,
        },
      ],
    }));
  };

  const removeAdvanceFolder = (id: string) => {
    markDirty((d) => ({
      ...d,
      advanceFolders: d.advanceFolders.filter((f) => f.folderId !== id),
    }));
  };

  const moveAdvanceFolder = (id: string, dir: -1 | 1) => {
    markDirty((d) => {
      const sorted = [...d.advanceFolders].sort(
        (a, b) => a.displayOrder - b.displayOrder,
      );
      const idx = sorted.findIndex((f) => f.folderId === id);
      const swap = idx + dir;
      if (idx < 0 || swap < 0 || swap >= sorted.length) return d;
      const tmp = sorted[idx].displayOrder;
      sorted[idx].displayOrder = sorted[swap].displayOrder;
      sorted[swap].displayOrder = tmp;
      return { ...d, advanceFolders: sorted };
    });
  };

  const toggleAdvanceFolderEnabled = (id: string) => {
    markDirty((d) => ({
      ...d,
      advanceFolders: d.advanceFolders.map((f) =>
        f.folderId === id ? { ...f, enabled: !f.enabled } : f,
      ),
    }));
  };

  return (
    <div className="space-y-6">
      <header className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <p className="text-xs text-muted">
            <Link href="/admin/templates" className="hover:text-foreground">
              Templates
            </Link>{" "}
            /{" "}
            <span className="text-foreground">{data.name || "Untitled"}</span>
          </p>
          <h1 className="mt-1 text-2xl font-semibold tracking-tight">
            {data.name || "Untitled template"}
          </h1>
          <div className="mt-2 flex items-center gap-2">
            <StatusBadge status={data.status} />
            <span className="text-xs text-muted">v{data.version}</span>
            <span className="text-xs text-muted" suppressHydrationWarning>
              · Updated {formatDate(data.updatedAt)}
            </span>
            {dirty ? (
              <span className="rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-800">
                Unsaved changes
              </span>
            ) : null}
          </div>
        </div>
        <div className="flex flex-wrap gap-2">
          <Button variant="secondary" size="sm" onClick={() => setShowPreview(true)}>
            Preview
          </Button>
          <Button variant="secondary" size="sm" onClick={duplicate} isLoading={saving}>
            Duplicate
          </Button>
          {data.status === "published" ? (
            <Button variant="secondary" size="sm" onClick={unpublish} disabled={saving}>
              Unpublish
            </Button>
          ) : null}
          {data.status !== "archived" ? (
            <Button variant="ghost" size="sm" onClick={archive} disabled={saving}>
              Archive
            </Button>
          ) : null}
          <Button variant="secondary" size="sm" onClick={saveDraft} isLoading={saving}>
            Save draft
          </Button>
          <Button size="sm" onClick={() => setShowPublishConfirm(true)} disabled={saving}>
            {data.status === "published" ? "Re-publish" : "Publish"}
          </Button>
        </div>
      </header>

      <section className="rounded-2xl border border-border bg-surface p-5 shadow-sm">
        <h2 className="text-sm font-semibold text-foreground">Template details</h2>
        <div className="mt-4 grid gap-4 sm:grid-cols-2">
          <Field label="Name">
            <input
              value={data.name}
              onChange={(e) => {
                const v = e.target.value;
                markDirty((d) => ({
                  ...d,
                  name: v,
                  slug: d.slug === slugify(d.name) || d.slug === "" ? slugify(v) : d.slug,
                }));
              }}
              className="input"
            />
          </Field>
          <Field label="Slug">
            <input
              value={data.slug}
              onChange={(e) => markDirty({ slug: slugify(e.target.value) })}
              className="input"
            />
          </Field>
          <Field label="Category">
            <input
              value={data.category}
              onChange={(e) => markDirty({ category: e.target.value })}
              className="input"
            />
          </Field>
          <Field label="Icon">
            <input
              value={data.icon}
              onChange={(e) => markDirty({ icon: e.target.value })}
              className="input"
            />
          </Field>
          <Field label="Description" full>
            <textarea
              value={data.description}
              onChange={(e) => markDirty({ description: e.target.value })}
              className="input min-h-[80px]"
              rows={3}
            />
          </Field>
          <Field label="Cover image URL" full>
            <input
              type="url"
              value={data.coverImage ?? ""}
              onChange={(e) =>
                markDirty({ coverImage: e.target.value || null })
              }
              placeholder="https://…"
              className="input"
            />
          </Field>
        </div>
      </section>

      <section className="rounded-2xl border border-border bg-surface p-5 shadow-sm">
        <h2 className="text-sm font-semibold text-foreground">
          Card appearance &amp; hover
        </h2>
        <p className="mt-1 text-xs text-muted">
          Upload a wide cover image for the card and an optional large hover
          image that fills the card on hover. Add a custom cursor image (a small
          transparent PNG / SVG / ICO) and a tagline that appears with it.
        </p>
        <div className="mt-4 grid gap-4 lg:grid-cols-2">
          <ImageUploadField
            label="Cover image (recommended 16:9)"
            value={data.coverImage}
            onChange={(url) => markDirty({ coverImage: url })}
            description="Shown as the main image on the template card."
          />
          <ImageUploadField
            label="Hover image (recommended 16:9 or 4:3)"
            value={data.hoverImage}
            onChange={(url) => markDirty({ hoverImage: url })}
            description="Replaces the cover when the user hovers the card."
          />
          <ImageUploadField
            label="Custom cursor (small PNG/SVG, transparent)"
            value={data.hoverCursor}
            onChange={(url) => markDirty({ hoverCursor: url })}
            description="Follows the mouse while hovering this card."
            small
          />
          <Field label="Hover tagline" full>
            <input
              type="text"
              value={data.hoverTagline ?? ""}
              onChange={(e) =>
                markDirty({ hoverTagline: e.target.value || null })
              }
              maxLength={120}
              placeholder="e.g. Plan your perfect wedding"
              className="input"
            />
          </Field>
        </div>
      </section>

      <section className="grid gap-6 lg:grid-cols-3">
        <div className="rounded-2xl border border-border bg-surface p-5 shadow-sm lg:col-span-2">
          <h2 className="text-sm font-semibold text-foreground">
            Selected modules ({orderedSelected.length})
          </h2>
          <p className="mt-1 text-xs text-muted">
            Implicit modules (event dates, location) are always included.
          </p>
          {orderedSelected.length === 0 ? (
            <p className="mt-3 text-sm text-muted">
              Add modules from the library on the right.
            </p>
          ) : (
            <ol className="mt-4 space-y-2">
              {orderedSelected.map((m, idx) => (
                <li
                  key={m.slug}
                  className={`flex items-center gap-2 rounded-xl border px-3 py-2 transition-colors ${
                    activeSlug === m.slug
                      ? "border-primary bg-primary/5"
                      : "border-border"
                  }`}
                >
                  <button
                    type="button"
                    onClick={() => setActiveSlug(m.slug)}
                    className="flex flex-1 items-center gap-2 text-left"
                  >
                    <span className="grid h-7 w-7 place-items-center rounded-md bg-surface-muted text-xs font-bold uppercase">
                      {m.icon?.[0] ?? m.name[0]}
                    </span>
                    <span className="flex-1 min-w-0">
                      <p className="truncate text-sm font-medium">{m.name}</p>
                      <p className="text-xs text-muted">
                        {m.isRequired ? "Required" : "Optional"} ·{" "}
                        {m.enabled ? "Enabled" : "Disabled"}
                      </p>
                    </span>
                  </button>
                  <button
                    type="button"
                    onClick={() => moveModule(m.slug, -1)}
                    disabled={idx === 0}
                    className="rounded-md p-1 text-muted hover:bg-surface-muted disabled:opacity-30"
                    aria-label="Move up"
                  >
                    ↑
                  </button>
                  <button
                    type="button"
                    onClick={() => moveModule(m.slug, 1)}
                    disabled={idx === orderedSelected.length - 1}
                    className="rounded-md p-1 text-muted hover:bg-surface-muted disabled:opacity-30"
                    aria-label="Move down"
                  >
                    ↓
                  </button>
                  <button
                    type="button"
                    onClick={() => toggleRequired(m.slug)}
                    className={`rounded-md px-2 py-1 text-xs ${
                      m.isRequired
                        ? "bg-primary/10 text-primary"
                        : "text-muted hover:bg-surface-muted"
                    }`}
                  >
                    Required
                  </button>
                  <button
                    type="button"
                    onClick={() => toggleEnabled(m.slug)}
                    className={`rounded-md px-2 py-1 text-xs ${
                      m.enabled
                        ? "bg-green-100 text-green-800"
                        : "text-muted hover:bg-surface-muted"
                    }`}
                  >
                    {m.enabled ? "On" : "Off"}
                  </button>
                  <button
                    type="button"
                    onClick={() => removeModule(m.slug)}
                    className="rounded-md p-1 text-red-600 hover:bg-red-50"
                    aria-label="Remove"
                  >
                    ✕
                  </button>
                </li>
              ))}
            </ol>
          )}

          {activeModule && activeMeta ? (
            <div className="mt-6 rounded-xl border border-border bg-surface-muted/40 p-4">
              <h3 className="text-sm font-semibold text-foreground">
                About: {activeMeta.name}
              </h3>
              <p className="mt-1 text-xs text-muted">{activeMeta.description}</p>
            </div>
          ) : null}

          {implicitModules.length > 0 ? (
            <div className="mt-6 rounded-xl border border-dashed border-border bg-surface-muted/30 p-4">
              <p className="text-xs font-medium uppercase tracking-wide text-muted">
                Always included
              </p>
              <ul className="mt-2 grid gap-1 sm:grid-cols-2">
                {implicitModules.map((m) => (
                  <li
                    key={m.slug}
                    className="rounded-lg bg-surface px-3 py-2 text-sm"
                  >
                    <span className="font-medium">{m.name}</span>{" "}
                    <span className="text-xs text-muted">— {m.description}</span>
                  </li>
                ))}
              </ul>
            </div>
          ) : null}
        </div>

        <div className="rounded-2xl border border-border bg-surface p-5 shadow-sm">
          <h2 className="text-sm font-semibold text-foreground">Module library</h2>
          <p className="mt-1 text-xs text-muted">
            Add a prebuilt module to include it in this template.
          </p>
          <div className="mt-3 max-h-[420px] space-y-2 overflow-y-auto pr-1">
            {libraryAvailable.length === 0 ? (
              <p className="text-xs text-muted">All modules are already added.</p>
            ) : (
              libraryAvailable.map((m) => (
                <div
                  key={m.slug}
                  className="rounded-lg border border-border bg-surface p-2"
                >
                  <div className="flex items-center gap-2">
                    <div className="flex-1 min-w-0">
                      <p className="truncate text-sm font-medium">{m.name}</p>
                      <p className="text-xs text-muted capitalize">
                        {m.category}
                      </p>
                    </div>
                    <button
                      type="button"
                      onClick={() => addModule(m)}
                      className="rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:bg-primary-hover"
                    >
                      Add
                    </button>
                  </div>
                  <p className="mt-1 text-[11px] text-muted">{m.description}</p>
                </div>
              ))
            )}
          </div>
        </div>
      </section>

      <section className="grid gap-6 lg:grid-cols-3">
        <div className="rounded-2xl border border-border bg-surface p-5 shadow-sm lg:col-span-2">
          <h2 className="text-sm font-semibold text-foreground">
            Advance folders ({orderedAdvanceFolders.length})
          </h2>
          <p className="mt-1 text-xs text-muted">
            Pick folders to expose on the customer event page. Products inside
            each folder are shown nested under the folder header.
          </p>
          {orderedAdvanceFolders.length === 0 ? (
            <p className="mt-3 text-sm text-muted">
              Add folders from the library on the right.
            </p>
          ) : (
            <ol className="mt-4 space-y-2">
              {orderedAdvanceFolders.map((f, idx) => {
                const meta = advanceFolderLibraryById.get(f.folderId);
                return (
                  <li
                    key={f.folderId}
                    className="flex items-center gap-2 rounded-xl border border-border px-3 py-2"
                  >
                    <div className="min-w-0 flex-1">
                      <p className="truncate text-sm font-medium">
                        {f.name || meta?.name}
                      </p>
                      {(f.description || meta?.description) ? (
                        <p className="truncate text-[11px] text-muted">
                          {f.description || meta?.description}
                        </p>
                      ) : null}
                      <p className="text-[10px] text-muted">
                        {f.enabled ? "Enabled" : "Disabled"}
                      </p>
                    </div>
                    <button
                      type="button"
                      onClick={() => moveAdvanceFolder(f.folderId, -1)}
                      disabled={idx === 0}
                      className="rounded-md p-1 text-muted hover:bg-surface-muted disabled:opacity-30"
                      aria-label="Move up"
                    >
                      ↑
                    </button>
                    <button
                      type="button"
                      onClick={() => moveAdvanceFolder(f.folderId, 1)}
                      disabled={idx === orderedAdvanceFolders.length - 1}
                      className="rounded-md p-1 text-muted hover:bg-surface-muted disabled:opacity-30"
                      aria-label="Move down"
                    >
                      ↓
                    </button>
                    <button
                      type="button"
                      onClick={() => toggleAdvanceFolderEnabled(f.folderId)}
                      className={`rounded-md px-2 py-1 text-xs ${
                        f.enabled
                          ? "bg-green-100 text-green-800"
                          : "text-muted hover:bg-surface-muted"
                      }`}
                    >
                      {f.enabled ? "On" : "Off"}
                    </button>
                    <button
                      type="button"
                      onClick={() => removeAdvanceFolder(f.folderId)}
                      className="rounded-md p-1 text-red-600 hover:bg-red-50"
                      aria-label="Remove"
                    >
                      ✕
                    </button>
                  </li>
                );
              })}
            </ol>
          )}
        </div>

        <div className="rounded-2xl border border-border bg-surface p-5 shadow-sm">
          <h2 className="text-sm font-semibold text-foreground">
            Advance folder library
          </h2>
          <p className="mt-1 text-xs text-muted">
            Folders created in Admin → Advance Modules. Click a folder to
            attach it to this template.
          </p>
          <div className="mt-3 max-h-[420px] space-y-2 overflow-y-auto pr-1">
            {advanceFolderLibrary.length === 0 ? (
              <p className="text-xs text-muted">
                No folders yet. Create folders in Admin → Advance Modules
                first.
              </p>
            ) : advanceFolderLibraryAvailable.length === 0 ? (
              <p className="text-xs text-muted">
                All folders are already attached.
              </p>
            ) : (
              advanceFolderLibraryAvailable.map((folder) => (
                <div
                  key={folder.id}
                  className="rounded-lg border border-border bg-surface p-2"
                >
                  <div className="flex items-center gap-2">
                    <div className="flex-1 min-w-0">
                      <p className="truncate text-sm font-medium">
                        {folder.name}
                      </p>
                      <p className="truncate text-[11px] text-muted">
                        {folder.description || folder.slug}
                      </p>
                    </div>
                    <button
                      type="button"
                      onClick={() => addAdvanceFolder(folder)}
                      className="rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:bg-primary-hover"
                    >
                      Add
                    </button>
                  </div>
                </div>
              ))
            )}
          </div>
        </div>
      </section>

      <section className="rounded-2xl border border-border bg-surface p-5 shadow-sm">
        <h2 className="text-sm font-semibold text-foreground">Template settings</h2>
        <div className="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
          {(
            [
              ["requireEventDate", "Event date required"],
              ["requireLocation", "Location required"],
              ["allowEndDate", "Allow end date"],
              ["allowMultipleFunctions", "Allow multiple functions"],
              ["allowFileUploads", "Allow file uploads"],
              ["allowCollaboration", "Allow collaboration"],
            ] as const
          ).map(([key, label]) => (
            <label
              key={key}
              className="flex items-center gap-2 rounded-lg border border-border bg-surface px-3 py-2 text-sm"
            >
              <input
                type="checkbox"
                checked={data.settings[key]}
                onChange={(e) =>
                  markDirty((d) => ({
                    ...d,
                    settings: { ...d.settings, [key]: e.target.checked },
                  }))
                }
              />
              <span>{label}</span>
            </label>
          ))}
        </div>
        <p className="mt-3 text-xs text-muted">
          Note: custom modules are no longer configurable; admins pick from
          prebuilt modules only.
        </p>
      </section>

      <ConfirmDialog
        open={showPublishConfirm}
        title={
          data.status === "published"
            ? "Re-publish template?"
            : "Publish template?"
        }
        description="Published templates become visible on the client templates page."
        confirmLabel={data.status === "published" ? "Re-publish" : "Publish"}
        onConfirm={publish}
        onCancel={() => setShowPublishConfirm(false)}
        pending={saving}
      />

      {showPreview ? (
        <PreviewOverlay
          template={data}
          implicitModules={implicitModules}
          onClose={() => setShowPreview(false)}
        />
      ) : null}

      <style jsx>{`
        :global(.input) {
          width: 100%;
          border-radius: 0.5rem;
          border: 1px solid var(--border);
          background: var(--surface);
          padding: 0.5rem 0.75rem;
          font-size: 0.875rem;
          color: var(--foreground);
        }
        :global(.input:focus) {
          outline: none;
          border-color: var(--primary);
        }
      `}</style>
    </div>
  );
}

function Field({
  label,
  full,
  children,
}: {
  label: string;
  full?: boolean;
  children: React.ReactNode;
}) {
  return (
    <div className={full ? "sm:col-span-2" : ""}>
      <label className="mb-1 block text-xs font-medium text-muted">{label}</label>
      {children}
    </div>
  );
}

function ImageUploadField({
  label,
  value,
  onChange,
  description,
  small,
}: {
  label: string;
  value: string | null;
  onChange: (url: string | null) => void;
  description?: string;
  small?: boolean;
}) {
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const handleFile = async (file: File | null) => {
    if (!file) return;
    setError(null);
    setUploading(true);
    try {
      const form = new FormData();
      form.append("file", file);
      const res = await fetch("/api/uploads", {
        method: "POST",
        body: form,
        credentials: "include",
      });
      const payload = (await res.json().catch(() => ({}))) as
        | { success: true; data: { url: string } }
        | { success: false; message: string };
      if (!res.ok || !("data" in payload) || !payload.success) {
        throw new Error(
          "message" in payload ? payload.message : "Upload failed.",
        );
      }
      onChange(payload.data.url);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Upload failed.");
    } finally {
      setUploading(false);
    }
  };

  return (
    <div>
      <label className="mb-1 block text-xs font-medium text-muted">{label}</label>
      <div className="flex items-start gap-3">
        <div
          className={`relative grid shrink-0 place-items-center overflow-hidden rounded-lg border border-dashed border-border bg-surface-muted ${
            small ? "h-16 w-16" : "h-24 w-32"
          }`}
        >
          {value ? (
            // eslint-disable-next-line @next/next/no-img-element
            <img
              src={value}
              alt=""
              className="h-full w-full object-cover"
            />
          ) : (
            <span className="text-[10px] font-medium uppercase text-muted">
              {small ? "cursor" : "no image"}
            </span>
          )}
        </div>
        <div className="flex-1 space-y-2">
          <input
            type="url"
            value={value ?? ""}
            onChange={(e) => onChange(e.target.value || null)}
            placeholder="https://… or upload below"
            className="input"
          />
          <div className="flex items-center gap-2">
            <label className="inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-border bg-surface px-3 py-1.5 text-xs font-medium text-foreground hover:bg-surface-muted">
              <input
                type="file"
                accept="image/png,image/jpeg,image/webp,image/gif,image/svg+xml,image/x-icon"
                className="hidden"
                onChange={(e) => {
                  const file = e.target.files?.[0] ?? null;
                  handleFile(file);
                  e.target.value = "";
                }}
              />
              {uploading ? "Uploading…" : "Upload"}
            </label>
            {value ? (
              <button
                type="button"
                onClick={() => onChange(null)}
                className="text-xs text-muted hover:text-red-600"
              >
                Remove
              </button>
            ) : null}
          </div>
          {error ? <p className="text-xs text-red-600">{error}</p> : null}
          {description ? (
            <p className="text-[11px] text-muted">{description}</p>
          ) : null}
        </div>
      </div>
    </div>
  );
}

function PreviewOverlay({
  template,
  implicitModules,
  onClose,
}: {
  template: TemplateData;
  implicitModules: TemplateModuleMeta[];
  onClose: () => void;
}) {
  const items = template.modules.filter((m) => m.enabled);
  return (
    <div className="fixed inset-0 z-50 grid place-items-center bg-black/40 p-4">
      <div className="w-full max-w-2xl rounded-2xl border border-border bg-surface p-6 shadow-lg">
        <div className="flex items-center justify-between">
          <div>
            <p className="text-xs text-muted">Preview</p>
            <h3 className="text-xl font-semibold">{template.name}</h3>
            <p className="mt-1 text-sm text-muted">{template.description}</p>
          </div>
          <button
            type="button"
            onClick={onClose}
            className="rounded-md p-1 text-muted hover:bg-surface-muted"
          >
            ✕
          </button>
        </div>
        <div className="mt-4 rounded-xl border border-border bg-surface-muted/40 p-4">
          <p className="text-sm font-semibold">Modules</p>
          <ul className="mt-2 grid gap-2 sm:grid-cols-2">
            {implicitModules.map((m) => (
              <li
                key={m.slug}
                className="rounded-lg border border-dashed border-border bg-surface px-3 py-2 text-sm font-medium"
              >
                {m.name} <span className="text-xs text-muted">(always)</span>
              </li>
            ))}
            {items.length === 0 ? (
              <li className="text-sm text-muted">No enabled modules.</li>
            ) : (
              items.map((m) => (
                <li
                  key={m.slug}
                  className="rounded-lg border border-border bg-surface px-3 py-2 text-sm font-medium"
                >
                  {m.name}
                </li>
              ))
            )}
          </ul>
        </div>
      </div>
    </div>
  );
}
