﻿"use client";

import Image from "next/image";
import { useCallback, useEffect, useMemo, useState } from "react";
import toast, { Toaster } from "react-hot-toast";
import { RichTextEditor } from "./RichTextEditor";

const API = process.env.NEXT_PUBLIC_API_URL || "http://localhost:5000/api";

type Campaign = {
  id: number;
  title: string;
  slug: string;
  short_description: string;
  description: string;
  cover_image_url: string | null;
  images: string[];
  goal_amount: number;
  raised_amount: number;
  category: string;
  status: string;
  start_date: string | null;
  end_date: string | null;
  beneficiaries_count: number;
  location: string | null;
  featured: number;
  created_at: string;
};

type ModalState =
  | { type: "none" }
  | { type: "create" }
  | { type: "edit"; row: Campaign }
  | { type: "delete"; row: Campaign };

const categoryLabels: Record<string, string> = {
  education: "Education", healthcare: "Healthcare", water: "Water", food: "Food",
  community: "Community", environment: "Environment", disaster: "Disaster Relief", other: "Other",
};

const categoryColors: Record<string, string> = {
  education: "var(--color-primary-deep)", healthcare: "#ea580c", water: "var(--color-ink)", food: "var(--color-ink)",
  community: "var(--color-primary-deep)", environment: "var(--color-primary-deep)", disaster: "var(--color-ink)", other: "var(--color-ink-mute)",
};

export function AdminCrowdfunding() {
  const [campaigns, setCampaigns] = useState<Campaign[]>([]);
  const [loading, setLoading] = useState(true);
  const [message, setMessage] = useState("");
  const [query, setQuery] = useState("");
  const [filter, setFilter] = useState("all");
  const [modal, setModal] = useState<ModalState>({ type: "none" });

  const token = useMemo(() => {
    if (typeof window === "undefined") return "";
    return localStorage.getItem("ngo_admin_token") || "";
  }, []);

  const loadCampaigns = useCallback(async () => {
    setLoading(true);
    const res = await fetch(`${API}/admin/crowdfunding`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    if (!res.ok) throw new Error("Failed to load");
    setCampaigns(await res.json());
    setLoading(false);
  }, [token]);

  useEffect(() => {
    const timer = window.setTimeout(() => {
      loadCampaigns().catch(() => { setMessage("Could not load campaigns."); setLoading(false); });
    }, 0);
    return () => window.clearTimeout(timer);
  }, [loadCampaigns]);

  const filtered = campaigns.filter((c) => {
    const matchesQuery = [c.title, c.category, c.location, c.short_description]
      .some((v) => String(v ?? "").toLowerCase().includes(query.toLowerCase()));
    const matchesFilter = filter === "all" || c.status === filter;
    return matchesQuery && matchesFilter;
  });

  const stats = useMemo(() => ({
    total: campaigns.length,
    active: campaigns.filter((c) => c.status === "active").length,
    totalRaised: campaigns.reduce((sum, c) => sum + Number(c.raised_amount), 0),
    totalGoal: campaigns.reduce((sum, c) => sum + Number(c.goal_amount), 0),
  }), [campaigns]);

  const saveCampaign = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setMessage("");
    const fd = new FormData(event.currentTarget);
    const hasFile = [...fd.values()].some((v) => v instanceof File && (v as File).size > 0);
    const editing = modal.type === "edit";
    const id = editing ? modal.row.id : "";

    if (hasFile) {
      const res = await fetch(`${API}/admin/crowdfunding${editing ? `/${id}` : ""}`, {
        method: editing ? "PUT" : "POST",
        headers: { Authorization: `Bearer ${token}` },
        body: fd,
      });
      if (!res.ok) { setMessage("Save failed."); return; }
    } else {
      const body: Record<string, unknown> = {};
      fd.forEach((val, key) => { body[key] = val === "" ? null : val; });
      const res = await fetch(`${API}/admin/crowdfunding${editing ? `/${id}` : ""}`, {
        method: editing ? "PUT" : "POST",
        headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
        body: JSON.stringify(body),
      });
      if (!res.ok) { setMessage("Save failed."); return; }
    }
    setModal({ type: "none" });
    setMessage(editing ? "Campaign updated." : "Campaign created.");
    toast.success(editing ? "Campaign updated!" : "Campaign created!");
    await loadCampaigns();
  };

  const deleteCampaign = async () => {
    if (modal.type !== "delete") return;
    const res = await fetch(`${API}/admin/crowdfunding/${modal.row.id}`, {
      method: "DELETE",
      headers: { Authorization: `Bearer ${token}` },
    });
    if (!res.ok) { setMessage("Delete failed."); return; }
    setModal({ type: "none" });
    setMessage("Campaign deleted.");
    toast.success("Campaign deleted!");
    await loadCampaigns();
  };

  return (
    <div className="mx-auto max-w-7xl">
      <div className="mb-5 flex flex-wrap items-center justify-between gap-3">
        <div>
          <p className="text-[10px] font-black uppercase tracking-[0.14em] text-[var(--color-primary)]">Fundraising</p>
          <h1 className="mt-0.5 text-xl font-black text-[var(--color-ink)]">Crowdfunding Campaigns</h1>
          <p className="mt-1 max-w-2xl text-[11.5px] font-medium text-[var(--color-ink-mute)]">Manage campaign goals, progress, images and public display.</p>
        </div>
        <button onClick={() => setModal({ type: "create" })} className="rounded-md bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-primary-deep)] px-3 py-1.5 text-[11.5px] font-black text-white shadow-[0_8px_18px_rgba(93,111,241,0.28)] transition hover:brightness-105">
          + New Campaign
        </button>
      </div>

      {message && <p className="mb-4 rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] p-3 text-[11.5px] font-bold text-[var(--color-primary-deep)]">{message}</p>}

      {/* Stats */}
      <div className="mb-5 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
        {[
          { label: "Total Campaigns", value: stats.total, color: "var(--color-primary)", bg: "var(--color-canvas-soft)" },
          { label: "Active", value: stats.active, color: "var(--color-primary-deep)", bg: "var(--color-canvas-soft)" },
          { label: "Total Raised", value: `Rs. ${stats.totalRaised.toLocaleString("en-IN")}`, color: "#ea580c", bg: "var(--color-canvas-soft)" },
          { label: "Total Goal", value: `Rs. ${stats.totalGoal.toLocaleString("en-IN")}`, color: "var(--color-ink)", bg: "var(--color-canvas-soft)" },
        ].map((s) => (
          <div key={s.label} className="rounded-md border border-[var(--color-hairline)] bg-white p-3.5 shadow-sm">
            <p className="text-[10px] font-black uppercase tracking-[0.12em] text-[var(--color-ink-mute)]">{s.label}</p>
            <p className="mt-1.5 text-lg font-black" style={{ color: s.color }}>{s.value}</p>
          </div>
        ))}
      </div>

      {/* Filter bar */}
      <div className="mb-4 flex flex-wrap items-center gap-2.5">
        <div className="flex min-w-0 flex-1 items-center gap-2 rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-1.5 text-[12px] sm:max-w-xs">
          <span className="font-black text-[var(--color-primary)]">Q</span>
          <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search campaigns..." className="min-w-0 flex-1 bg-transparent outline-none" />
        </div>
        <div className="flex flex-wrap gap-1">
          {["all", "active", "draft", "completed", "cancelled"].map((s) => (
            <button key={s} onClick={() => setFilter(s)} className={`rounded-md px-2.5 py-1 text-[11px] font-black transition ${filter === s ? "bg-[var(--color-primary)] text-white" : "border border-[var(--color-hairline)] bg-white text-[var(--color-ink-mute)] hover:border-[var(--color-primary)]"}`}>
              {s === "all" ? "All" : s.charAt(0).toUpperCase() + s.slice(1)}
            </button>
          ))}
        </div>
      </div>

      {/* Campaign cards */}
      {loading ? (
        <div className="rounded-md border border-[var(--color-hairline)] bg-white p-6 text-center text-[12px] font-black text-[var(--color-ink-mute)]">Loading campaigns...</div>
      ) : filtered.length === 0 ? (
        <div className="rounded-md border border-[var(--color-hairline)] bg-white p-6 text-center text-[12px] font-bold text-[var(--color-ink-mute)]">No campaigns found.</div>
      ) : (
        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          {filtered.map((c) => {
            const pct = Number(c.goal_amount) > 0 ? Math.min(100, Math.round((Number(c.raised_amount) / Number(c.goal_amount)) * 100)) : 0;
            return (
              <article key={c.id} className="group overflow-hidden rounded-md border border-[var(--color-hairline)] bg-white shadow-sm transition hover:-translate-y-0.5 hover:shadow-md">
                <div className="relative h-44 overflow-hidden">
                  {c.cover_image_url ? (
                    <Image src={c.cover_image_url} alt={c.title} fill className="object-cover transition duration-300 group-hover:scale-105" sizes="(max-width: 768px) 100vw, 33vw" />
                  ) : (
                    <div className="flex h-full items-center justify-center" style={{ background: `${categoryColors[c.category] || "var(--color-ink-mute)"}15` }}>
                      <span className="text-4xl font-black" style={{ color: `${categoryColors[c.category] || "var(--color-ink-mute)"}30` }}>{c.title.charAt(0)}</span>
                    </div>
                  )}
                  <div className="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent" />
                  <div className="absolute left-3 top-3 flex gap-2">
                    <span className="rounded-full px-2.5 py-1 text-[10px] font-black uppercase text-white" style={{ background: categoryColors[c.category] || "var(--color-ink-mute)" }}>
                      {categoryLabels[c.category] || c.category}
                    </span>
                    {c.featured ? <span className="rounded-full bg-[#d97706] px-2.5 py-1 text-[10px] font-black uppercase text-[var(--color-canvas-night)]">Featured</span> : null}
                  </div>
                  <span className={`absolute right-3 top-3 rounded-full px-2.5 py-1 text-[10px] font-black uppercase text-white ${c.status === "active" ? "bg-[var(--color-primary-deep)]" : c.status === "draft" ? "bg-[var(--color-ink-mute)]" : c.status === "completed" ? "bg-[var(--color-primary-deep)]" : "bg-[var(--color-ink)]"}`}>
                    {c.status}
                  </span>
                </div>
                <div className="p-4">
                  <h3 className="truncate text-base font-black text-[var(--color-ink)]">{c.title}</h3>
                  <p className="mt-1 line-clamp-2 text-[12px] text-[var(--color-ink-mute)]">{c.short_description}</p>

                  <div className="mt-3">
                    <div className="flex items-center justify-between text-[11px] font-bold text-[var(--color-ink-mute)]">
                      <span>Rs. {Number(c.raised_amount).toLocaleString("en-IN")}</span>
                      <span>{pct}%</span>
                    </div>
                    <div className="mt-1.5 h-1.5 w-full overflow-hidden rounded-full bg-[var(--color-hairline)]">
                      <div className="h-full rounded-full" style={{ width: `${pct}%`, background: `linear-gradient(90deg, ${categoryColors[c.category] || "var(--color-primary)"}, ${categoryColors[c.category] || "var(--color-primary)"}cc)` }} />
                    </div>
                    <div className="mt-1 flex items-center justify-between text-[10px] font-bold text-[var(--color-ink-mute)]">
                      <span>Goal: Rs. {Number(c.goal_amount).toLocaleString("en-IN")}</span>
                      {c.end_date && <span>Ends {new Date(c.end_date).toLocaleDateString("en-IN", { day: "2-digit", month: "short", year: "numeric" })}</span>}
                    </div>
                  </div>

                  <div className="mt-3 flex items-center justify-between border-t border-[var(--color-hairline)] pt-3">
                    <div className="flex items-center gap-2 text-[10px] font-bold text-[var(--color-ink-mute)]">
                      {c.beneficiaries_count > 0 && <span>{c.beneficiaries_count.toLocaleString("en-IN")} beneficiaries</span>}
                      {c.location && <span>{c.location}</span>}
                    </div>
                    <div className="flex gap-1">
                      <button onClick={() => setModal({ type: "edit", row: c })} className="rounded-md border border-[var(--color-hairline)] bg-white px-2.5 py-1 text-[11px] font-black text-[var(--color-ink)] transition hover:border-[var(--color-primary)] hover:text-[var(--color-primary)]">Edit</button>
                      <button onClick={() => setModal({ type: "delete", row: c })} className="rounded-md bg-[var(--color-canvas-soft)] px-2.5 py-1 text-[11px] font-black text-[var(--color-ink)] transition hover:bg-[var(--color-ink)] hover:text-white">Delete</button>
                    </div>
                  </div>
                </div>
              </article>
            );
          })}
        </div>
      )}

      {/* Create/Edit Modal */}
      {(modal.type === "create" || modal.type === "edit") && (
        <CampaignModal
          campaign={modal.type === "edit" ? modal.row : null}
          onClose={() => setModal({ type: "none" })}
          onSubmit={saveCampaign}
        />
      )}

      {/* Delete Modal */}
      {modal.type === "delete" && (
        <div className="fixed inset-0 z-[80] grid place-items-center bg-black/45 p-4 backdrop-blur-sm">
          <section className="w-full max-w-md rounded-md bg-white p-4 shadow-2xl">
            <p className="text-[10px] font-black uppercase tracking-[0.14em] text-[var(--color-ink)]">Confirm delete</p>
            <h2 className="mt-1.5 text-[13.5px] font-black text-[var(--color-ink)]">Delete Campaign</h2>
            <p className="mt-2 text-[12px] leading-6 text-[var(--color-ink-mute)]">This will permanently delete &quot;{modal.row.title}&quot;. This action cannot be undone.</p>
            <div className="mt-4 flex justify-end gap-2">
              <button onClick={() => setModal({ type: "none" })} className="rounded-md border border-[var(--color-hairline)] px-3 py-2 text-[11.5px] font-black text-[var(--color-ink)] transition hover:border-[var(--color-primary)] hover:text-[var(--color-primary)]">Cancel</button>
              <button onClick={deleteCampaign} className="rounded-md bg-[var(--color-ink)] px-3 py-2 text-[11.5px] font-black text-white transition hover:bg-[var(--color-ink)]">Delete</button>
            </div>
          </section>
        </div>
      )}

      <Toaster position="top-center" toastOptions={{ duration: 4000, style: { background: "#333", color: "#fff", fontSize: "14px", fontWeight: 600 } }} />
    </div>
  );
}

function CampaignModal({
  campaign,
  onClose,
  onSubmit,
}: {
  campaign: Campaign | null;
  onClose: () => void;
  onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
}) {
  const [html, setHtml] = useState(campaign?.description || "");
  const [coverPreview, setCoverPreview] = useState(campaign?.cover_image_url || "");
  const [existingImages, setExistingImages] = useState<string[]>(campaign?.images || []);
  const [newImagePreviews, setNewImagePreviews] = useState<string[]>([]);

  const handleCoverChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) setCoverPreview(URL.createObjectURL(file));
  };

  const handleImagesChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files;
    if (!files) return;
    setNewImagePreviews((prev) => [...prev, ...Array.from(files).map((f) => URL.createObjectURL(f))]);
  };

  const removeExistingImage = (index: number) => setExistingImages((prev) => prev.filter((_, i) => i !== index));
  const removeNewImage = (index: number) => setNewImagePreviews((prev) => prev.filter((_, i) => i !== index));

  return (
    <div className="fixed inset-0 z-[80] grid place-items-center bg-black/45 p-4 backdrop-blur-sm">
      <section className="max-h-[90vh] w-full max-w-3xl overflow-hidden rounded-md bg-white shadow-2xl">
        <header className="flex items-center justify-between border-b border-[var(--color-hairline)] px-4 py-3">
          <div>
            <p className="text-[10px] font-black uppercase tracking-[0.14em] text-[var(--color-primary)]">Campaign form</p>
            <h2 className="mt-0.5 text-[13.5px] font-black text-[var(--color-ink)]">{campaign ? "Edit Campaign" : "New Campaign"}</h2>
          </div>
          <button onClick={onClose} className="rounded-md border border-[var(--color-hairline)] px-2.5 py-1.5 text-[11.5px] font-black text-[var(--color-ink)] transition hover:border-[var(--color-primary)] hover:text-[var(--color-primary)]">Close</button>
        </header>
        <form onSubmit={onSubmit} className="max-h-[75vh] overflow-y-auto p-4">
          <input type="hidden" name="description" value={html} />
          <input type="hidden" name="images" value={JSON.stringify(existingImages)} />

          <div className="grid gap-3 md:grid-cols-2">
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Title *</span>
              <input name="title" required defaultValue={campaign?.title} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Slug</span>
              <input name="slug" defaultValue={campaign?.slug} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Category *</span>
              <select name="category" required defaultValue={campaign?.category || "education"} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10">
                {Object.entries(categoryLabels).map(([val, label]) => <option key={val} value={val}>{label}</option>)}
              </select>
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Status *</span>
              <select name="status" required defaultValue={campaign?.status || "draft"} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10">
                <option value="draft">Draft</option>
                <option value="active">Active</option>
                <option value="completed">Completed</option>
                <option value="cancelled">Cancelled</option>
              </select>
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Goal Amount (Rs.) *</span>
              <input name="goal_amount" type="number" required defaultValue={campaign?.goal_amount} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Raised Amount (Rs.)</span>
              <input name="raised_amount" type="number" defaultValue={campaign?.raised_amount || 0} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Start Date</span>
              <input name="start_date" type="date" defaultValue={campaign?.start_date?.slice(0, 10)} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">End Date</span>
              <input name="end_date" type="date" defaultValue={campaign?.end_date?.slice(0, 10)} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Beneficiaries Count</span>
              <input name="beneficiaries_count" type="number" defaultValue={campaign?.beneficiaries_count || 0} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Location</span>
              <input name="location" defaultValue={campaign?.location || ""} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Featured</span>
              <select name="featured" defaultValue={campaign?.featured ? "1" : "0"} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10">
                <option value="0">No</option>
                <option value="1">Yes</option>
              </select>
            </label>
          </div>

          <label className="mt-3 block">
            <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Short Description *</span>
            <textarea name="short_description" required defaultValue={campaign?.short_description} rows={3} className="w-full rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-2.5 py-2 text-[12px] font-medium outline-none focus:border-[var(--color-primary)] focus:ring-4 focus:ring-[var(--color-primary)]/10" />
          </label>

          <div className="mt-3">
            <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Detailed Description *</span>
            <RichTextEditor value={html} onChange={setHtml} placeholder="Write campaign description..." />
          </div>

          <label className="mt-3 block">
            <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Cover Image</span>
            <div className="flex items-center gap-3">
              {coverPreview ? (
                <Image src={coverPreview} alt="" width={72} height={56} className="h-14 w-18 rounded-md object-cover border border-[var(--color-hairline)]" />
              ) : (
                <div className="flex h-14 w-18 items-center justify-center rounded-md border border-dashed border-[var(--color-hairline)] text-[10px] font-bold text-[var(--color-ink-mute)]">No img</div>
              )}
              <label className="flex cursor-pointer items-center justify-center gap-2 rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-3 py-2 text-[11.5px] font-bold text-[var(--color-ink)] transition hover:bg-[var(--color-canvas-soft)]">
                Choose cover
                <input name="files" type="file" accept="image/*" className="hidden" onChange={handleCoverChange} />
              </label>
            </div>
          </label>

          <div className="mt-3">
            <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Gallery Images</span>
            <div className="grid grid-cols-4 gap-2">
              {existingImages.map((url, i) => (
                <div key={`ex-${i}`} className="relative group">
                  <Image src={url} alt="" width={120} height={80} className="h-18 w-full rounded-md object-cover border border-[var(--color-hairline)]" />
                  <button type="button" onClick={() => removeExistingImage(i)} className="absolute -top-1.5 -right-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-[var(--color-ink)] text-white text-[10px] font-bold opacity-0 group-hover:opacity-100 transition">&times;</button>
                </div>
              ))}
              {newImagePreviews.map((url, i) => (
                <div key={`new-${i}`} className="relative group">
                  <Image src={url} alt="" width={120} height={80} className="h-18 w-full rounded-md object-cover border border-[var(--color-hairline)]" />
                  <button type="button" onClick={() => removeNewImage(i)} className="absolute -top-1.5 -right-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-[var(--color-ink)] text-white text-[10px] font-bold opacity-0 group-hover:opacity-100 transition">&times;</button>
                </div>
              ))}
              <label className="flex h-18 cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-[var(--color-hairline)] text-[10px] font-bold text-[var(--color-ink-mute)] transition hover:border-[var(--color-primary)] hover:text-[var(--color-primary)]">
                + Add
                <input type="file" accept="image/*" multiple name="files" className="hidden" onChange={handleImagesChange} />
              </label>
            </div>
          </div>

          <div className="mt-4 flex justify-end gap-2 border-t border-[var(--color-hairline)] pt-4">
            <button type="button" onClick={onClose} className="rounded-md border border-[var(--color-hairline)] px-3 py-2 text-[11.5px] font-black text-[var(--color-ink)] transition hover:border-[var(--color-primary)] hover:text-[var(--color-primary)]">Cancel</button>
            <button className="rounded-md bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-primary-deep)] px-4 py-2 text-[11.5px] font-black text-white shadow-[0_8px_18px_rgba(93,111,241,0.28)] transition hover:brightness-105">{campaign ? "Update Campaign" : "Create Campaign"}</button>
          </div>
        </form>
      </section>
    </div>
  );
}
