﻿"use client";

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

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

type GalleryItem = {
  id: number;
  media_url: string;
  media_type: "image" | "video";
  video_url?: string | null;
  title: string;
  description?: string;
  category: string;
  sort_order: number;
  is_active: number;
  created_at?: string;
};

type ModalState =
  | { type: "none" }
  | { type: "upload" }
  | { type: "edit"; item: GalleryItem }
  | { type: "delete"; item: GalleryItem };

export function AdminGallery() {
  const [items, setItems] = useState<GalleryItem[]>([]);
  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 filtered = items.filter((item) => {
    const matchesQuery = [item.title, item.category, item.description]
      .some((v) => String(v ?? "").toLowerCase().includes(query.toLowerCase()));
    const matchesFilter = filter === "All" || item.category === filter;
    return matchesQuery && matchesFilter;
  });

  const categories = ["All", ...new Set(items.map((i) => i.category))];

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

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

  const deleteItem = async () => {
    if (modal.type !== "delete") return;
    const res = await fetch(`${API}/admin/gallery/${modal.item.id}`, {
      method: "DELETE",
      headers: { Authorization: `Bearer ${token}` },
    });
    if (!res.ok) return setMessage("Delete failed.");
    setModal({ type: "none" });
    setMessage("Item deleted.");
    await loadItems();
  };

  return (
    <div className="mx-auto max-w-7xl">
      <div className="mb-5 flex flex-wrap items-end justify-between gap-3">
        <div>
          <p className="text-[10px] font-black uppercase tracking-[0.14em] text-[var(--color-primary)]">Media</p>
          <h1 className="mt-0.5 text-xl font-black text-[var(--color-ink)] md:text-2xl">Gallery</h1>
          <p className="mt-1 max-w-2xl text-[11.5px] font-medium text-[var(--color-ink-mute)]">Upload and manage images and videos for the public gallery.</p>
        </div>
        <button onClick={() => setModal({ type: "upload" })} 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">
          Upload Files
        </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-ink)]">{message}</p> : null}

      <section className="overflow-hidden rounded-md border border-[var(--color-hairline)] bg-white shadow-sm">
        <div className="flex flex-wrap items-center justify-between gap-3 border-b border-[var(--color-hairline)] bg-white p-3.5">
          <div className="flex flex-wrap items-center gap-1.5">
            {categories.map((cat) => (
              <button
                key={cat}
                onClick={() => setFilter(cat)}
                className={`rounded-full px-2.5 py-1 text-[11px] font-bold transition ${
                  filter === cat ? "bg-[var(--color-primary)] text-white" : "bg-[var(--color-canvas-soft)] text-[var(--color-ink-mute)] hover:bg-[var(--color-canvas-soft)]"
                }`}
              >
                {cat}
              </button>
            ))}
          </div>
          <label className="flex min-h-10 w-full max-w-sm items-center gap-3 rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)] px-3">
            <span className="text-[11.5px] font-black text-[var(--color-primary)]">Q</span>
            <input
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              className="w-full bg-transparent text-[12px] font-semibold text-[var(--color-ink)] outline-none placeholder:text-[var(--color-ink-mute)]"
              placeholder="Search gallery"
            />
          </label>
        </div>

        <div className="p-3.5">
          <p className="mb-3 text-[12px] font-bold text-[var(--color-ink-mute)]">{filtered.length} items</p>
          {loading ? (
            <p className="py-8 text-center text-[12px] font-bold text-[var(--color-ink-mute)]">Loading...</p>
          ) : filtered.length === 0 ? (
            <p className="py-8 text-center text-[12px] font-bold text-[var(--color-ink-mute)]">No items found.</p>
          ) : (
            <div className="grid grid-cols-2 gap-2.5 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5">
              {filtered.map((item) => (
                <div key={item.id} className="group relative overflow-hidden rounded-md border border-[var(--color-hairline)] bg-[var(--color-canvas-soft)]">
                  <div className="relative aspect-square overflow-hidden">
                    {item.media_type === "video" && item.video_url ? (
                      <video src={item.video_url} className="h-full w-full object-cover" muted />
                    ) : item.media_url ? (
                      <img src={item.media_url} alt={item.title} className="h-full w-full object-cover" />
                    ) : (
                      <div className="grid h-full w-full place-items-center bg-[var(--color-canvas-soft)] text-[var(--color-ink-mute)]">No media</div>
                    )}
                    {item.media_type === "video" && (
                      <div className="absolute inset-0 grid place-items-center bg-black/20">
                        <span className="grid h-10 w-10 place-items-center rounded-full bg-white/90 text-lg">â–¶</span>
                      </div>
                    )}
                    <div className="absolute inset-0 bg-black/0 transition group-hover:bg-black/40" />
                    <div className="absolute bottom-0 left-0 right-0 flex justify-center gap-1.5 p-1.5 opacity-0 transition group-hover:opacity-100">
                      <button onClick={() => setModal({ type: "edit", item })} className="rounded-md bg-white px-2.5 py-1 text-[11px] font-black text-[var(--color-ink)]">Edit</button>
                      <button onClick={() => setModal({ type: "delete", item })} className="rounded-md bg-[var(--color-ink)] px-2.5 py-1 text-[11px] font-black text-white">Delete</button>
                    </div>
                  </div>
                  <div className="p-1.5">
                    <p className="truncate text-[11px] font-bold text-[var(--color-ink)]">{item.title}</p>
                    <p className="truncate text-[10px] text-[var(--color-ink-mute)]">{item.category}</p>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      </section>

      {modal.type === "upload" && (
        <UploadModal
          token={token}
          onClose={() => setModal({ type: "none" })}
          onDone={async () => { setModal({ type: "none" }); setMessage("Files uploaded."); await loadItems(); }}
        />
      )}

      {modal.type === "edit" && (
        <EditModal
          item={modal.item}
          token={token}
          onClose={() => setModal({ type: "none" })}
          onDone={async () => { setModal({ type: "none" }); setMessage("Item updated."); await loadItems(); }}
        />
      )}

      {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 item?</h2>
            <p className="mt-2 text-[12px] leading-6 text-[var(--color-ink-mute)]">This will permanently delete &quot;{modal.item.title}&quot;.</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={deleteItem} 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 UploadModal({
  token,
  onClose,
  onDone,
}: {
  token: string;
  onClose: () => void;
  onDone: () => void;
}) {
  const [files, setFiles] = useState<File[]>([]);
  const [previews, setPreviews] = useState<string[]>([]);
  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [category, setCategory] = useState("General");
  const [uploading, setUploading] = useState(false);

  const handleFiles = (e: React.ChangeEvent<HTMLInputElement>) => {
    const selected = Array.from(e.target.files || []);
    setFiles(selected);
    setPreviews(selected.map((f) => URL.createObjectURL(f)));
  };

  const upload = async () => {
    if (files.length === 0) return;
    setUploading(true);
    const fd = new FormData();
    files.forEach((f) => fd.append("files", f));
    fd.append("title", title);
    fd.append("description", description);
    fd.append("category", category);

    const res = await fetch(`${API}/admin/gallery`, {
      method: "POST",
      headers: { Authorization: `Bearer ${token}` },
      body: fd,
    });
    setUploading(false);
    if (!res.ok) return toast.error("Upload failed.");
    toast.success(`${files.length} file(s) uploaded.`);
    onDone();
  };

  return (
    <div className="fixed inset-0 z-[80] grid place-items-center bg-black/45 p-4 backdrop-blur-sm">
      <section className="max-h-[88vh] w-full max-w-2xl 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)]">Upload</p>
            <h2 className="mt-0.5 text-[13.5px] font-black text-[var(--color-ink)]">Add Gallery Files</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>
        <div className="max-h-[70vh] overflow-y-auto p-4">
          <div className="grid gap-3 md:grid-cols-2">
            <label className="md:col-span-2">
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Files (Images & Videos)</span>
              <input
                type="file"
                multiple
                accept="image/*,video/*"
                onChange={handleFiles}
                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)]"
              />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Title (applies to all)</span>
              <input value={title} onChange={(e) => setTitle(e.target.value)} 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)]" placeholder="Optional â€” defaults to filename" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Category</span>
              <select value={category} onChange={(e) => setCategory(e.target.value)} 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)]">
                {["General", "Events", "Projects", "Community", "Healthcare", "Education"].map((c) => <option key={c}>{c}</option>)}
              </select>
            </label>
            <label className="md:col-span-2">
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Description (applies to all)</span>
              <textarea value={description} onChange={(e) => setDescription(e.target.value)} className="min-h-20 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)]" />
            </label>
          </div>

          {previews.length > 0 && (
            <div className="mt-3 grid grid-cols-4 gap-2">
              {previews.map((src, i) => (
                <div key={i} className="relative aspect-square overflow-hidden rounded-md border border-[var(--color-hairline)]">
                  {files[i]?.type.startsWith("video/") ? (
                    <video src={src} className="h-full w-full object-cover" muted />
                  ) : (
                    <img src={src} alt="" className="h-full w-full object-cover" />
                  )}
                </div>
              ))}
            </div>
          )}

          <div className="mt-4 flex justify-end gap-2 border-t border-[var(--color-hairline)] pt-4">
            <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 onClick={upload} disabled={files.length === 0 || uploading} 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)] disabled:opacity-50 transition hover:brightness-105">
              {uploading ? "Uploading..." : `Upload ${files.length} file(s)`}
            </button>
          </div>
        </div>
      </section>
    </div>
  );
}

function EditModal({
  item,
  token,
  onClose,
  onDone,
}: {
  item: GalleryItem;
  token: string;
  onClose: () => void;
  onDone: () => void;
}) {
  const [title, setTitle] = useState(item.title);
  const [description, setDescription] = useState(item.description || "");
  const [category, setCategory] = useState(item.category);
  const [sortOrder, setSortOrder] = useState(item.sort_order);
  const [isActive, setIsActive] = useState(item.is_active === 1);
  const [file, setFile] = useState<File | null>(null);
  const [preview, setPreview] = useState(item.media_url);
  const [saving, setSaving] = useState(false);

  const save = async () => {
    setSaving(true);
    const fd = new FormData();
    if (file) fd.append("file", file);
    fd.append("title", title);
    fd.append("description", description);
    fd.append("category", category);
    fd.append("sort_order", String(sortOrder));
    fd.append("is_active", isActive ? "Active" : "Deactive");

    const res = await fetch(`${API}/admin/gallery/${item.id}`, {
      method: "PUT",
      headers: { Authorization: `Bearer ${token}` },
      body: fd,
    });
    setSaving(false);
    if (!res.ok) return toast.error("Update failed.");
    toast.success("Updated.");
    onDone();
  };

  return (
    <div className="fixed inset-0 z-[80] grid place-items-center bg-black/45 p-4 backdrop-blur-sm">
      <section className="max-h-[88vh] w-full max-w-2xl 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)]">Edit</p>
            <h2 className="mt-0.5 text-[13.5px] font-black text-[var(--color-ink)]">Edit Gallery Item</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>
        <div className="max-h-[70vh] overflow-y-auto p-4">
          <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 value={title} onChange={(e) => setTitle(e.target.value)} 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)]" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Category</span>
              <select value={category} onChange={(e) => setCategory(e.target.value)} 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)]">
                {["General", "Events", "Projects", "Community", "Healthcare", "Education"].map((c) => <option key={c}>{c}</option>)}
              </select>
            </label>
            <label className="md:col-span-2">
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Description</span>
              <textarea value={description} onChange={(e) => setDescription(e.target.value)} className="min-h-20 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)]" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Sort Order</span>
              <input type="number" value={sortOrder} onChange={(e) => setSortOrder(Number(e.target.value))} 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)]" />
            </label>
            <label>
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Active</span>
              <select value={isActive ? "1" : "0"} onChange={(e) => setIsActive(e.target.value === "1")} 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)]">
                <option value="1">Active</option>
                <option value="0">Deactive</option>
              </select>
            </label>
            <label className="md:col-span-2">
              <span className="mb-1.5 block text-[11.5px] font-black text-[var(--color-ink)]">Replace File (optional)</span>
              <div className="flex items-center gap-3">
                {preview && (
                  item.media_type === "video" ? (
                    <video src={preview} className="h-14 w-14 rounded-md object-cover" muted />
                  ) : (
                    <img src={preview} alt="" className="h-14 w-14 rounded-md object-cover" />
                  )
                )}
                <input type="file" accept="image/*,video/*" onChange={(e) => {
                  const f = e.target.files?.[0];
                  if (f) { setFile(f); setPreview(URL.createObjectURL(f)); }
                }} 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)]" />
              </div>
            </label>
          </div>
          <div className="mt-4 flex justify-end gap-2 border-t border-[var(--color-hairline)] pt-4">
            <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 onClick={save} disabled={saving} 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)] disabled:opacity-50 transition hover:brightness-105">
              {saving ? "Saving..." : "Save"}
            </button>
          </div>
        </div>
      </section>
    </div>
  );
}
