"use client";

import { useRef, useState } from "react";
import { useRouter } from "next/navigation";

export interface AdminPhoto {
  id: string;
  url: string;
  sort_order: number;
}
export interface AdminAlbum {
  id: string;
  slug: string;
  title: string;
  concept: string | null;
  date_label: string | null;
  venue: string | null;
  sort_order: number;
  event_id?: string | null;
  gallery_photos: AdminPhoto[];
}
export interface LinkableEvent {
  id: string;
  title: string;
  starts_at: string;
}

export default function GalleryManager({
  initial,
  events,
}: {
  initial: AdminAlbum[];
  events: LinkableEvent[];
}) {
  const router = useRouter();
  const [albums, setAlbums] = useState<AdminAlbum[]>(initial);
  const [title, setTitle] = useState("");
  const [venue, setVenue] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  async function addAlbum(e: React.FormEvent) {
    e.preventDefault();
    if (!title.trim()) return;
    setBusy(true);
    setError(null);
    const res = await fetch("/api/admin/gallery/albums", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ title: title.trim(), venue: venue || undefined }),
    });
    const data = await res.json().catch(() => ({}));
    setBusy(false);
    if (!res.ok) {
      setError(data.error || "Could not create album");
      return;
    }
    setAlbums([...albums, { ...(data as Omit<AdminAlbum, "gallery_photos">), gallery_photos: [] }]);
    setTitle("");
    setVenue("");
    router.refresh();
  }

  async function deleteAlbum(id: string) {
    const prev = albums;
    setAlbums(albums.filter((a) => a.id !== id));
    const res = await fetch(`/api/admin/gallery/albums/${id}`, { method: "DELETE" });
    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      setError(data.error || "Could not delete album");
      setAlbums(prev);
      return;
    }
    router.refresh();
  }

  async function uploadPhotos(album: AdminAlbum, files: FileList) {
    setError(null);
    const added: AdminPhoto[] = [];
    let order = album.gallery_photos.length;
    for (const file of Array.from(files)) {
      const form = new FormData();
      form.append("file", file);
      form.append("folder", `gallery/${album.slug}`);
      const upRes = await fetch("/api/uploads", { method: "POST", body: form });
      const upData = await upRes.json().catch(() => ({}));
      if (!upRes.ok) {
        setError(upData.error || "Upload failed");
        continue;
      }
      order += 1;
      const res = await fetch("/api/admin/gallery/photos", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ albumId: album.id, url: upData.url, sortOrder: order }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) {
        setError(data.error || "Could not save photo");
        continue;
      }
      added.push(data as AdminPhoto);
    }
    setAlbums(
      albums.map((a) =>
        a.id === album.id ? { ...a, gallery_photos: [...a.gallery_photos, ...added] } : a
      )
    );
    router.refresh();
  }

  async function linkEvent(albumId: string, eventId: string | null) {
    const prev = albums;
    setAlbums(albums.map((a) => (a.id === albumId ? { ...a, event_id: eventId } : a)));
    const res = await fetch(`/api/admin/gallery/albums/${albumId}`, {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ eventId }),
    });
    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      setError(data.error || "Could not link event");
      setAlbums(prev);
      return;
    }
    router.refresh();
  }

  async function deletePhoto(albumId: string, photoId: string) {
    setAlbums(
      albums.map((a) =>
        a.id === albumId
          ? { ...a, gallery_photos: a.gallery_photos.filter((p) => p.id !== photoId) }
          : a
      )
    );
    await fetch(`/api/admin/gallery/photos/${photoId}`, { method: "DELETE" });
    router.refresh();
  }

  return (
    <div className="space-y-6">
      {albums.map((album) => (
        <AlbumCard
          key={album.id}
          album={album}
          events={events}
          onUpload={uploadPhotos}
          onDeletePhoto={deletePhoto}
          onDeleteAlbum={deleteAlbum}
          onLinkEvent={linkEvent}
        />
      ))}
      {!albums.length && <p className="text-sm text-be-muted">No albums yet.</p>}

      <form onSubmit={addAlbum} className="rounded-lg border border-be-border bg-be-surface p-4">
        <p className="text-sm font-medium mb-3">New album</p>
        <div className="grid gap-2 sm:grid-cols-2">
          <input
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            placeholder="Album title"
            className="input"
          />
          <input
            value={venue}
            onChange={(e) => setVenue(e.target.value)}
            placeholder="Venue (optional)"
            className="input"
          />
        </div>
        <button
          type="submit"
          disabled={busy}
          className="mt-3 rounded-md bg-brand-green px-4 py-2 text-sm font-medium text-white hover:bg-brand-green-deep disabled:opacity-50"
        >
          Create album
        </button>
        {error && <p className="mt-2 text-sm text-red-600">{error}</p>}
      </form>
    </div>
  );
}

function AlbumCard({
  album,
  events,
  onUpload,
  onDeletePhoto,
  onDeleteAlbum,
  onLinkEvent,
}: {
  album: AdminAlbum;
  events: LinkableEvent[];
  onUpload: (album: AdminAlbum, files: FileList) => Promise<void>;
  onDeletePhoto: (albumId: string, photoId: string) => Promise<void>;
  onDeleteAlbum: (id: string) => Promise<void>;
  onLinkEvent: (albumId: string, eventId: string | null) => Promise<void>;
}) {
  const fileRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);

  async function handle(e: React.ChangeEvent<HTMLInputElement>) {
    if (!e.target.files?.length) return;
    setUploading(true);
    await onUpload(album, e.target.files);
    setUploading(false);
    if (fileRef.current) fileRef.current.value = "";
  }

  return (
    <div className="rounded-lg border border-be-border bg-be-surface p-4">
      <div className="flex items-center justify-between">
        <div>
          <p className="font-medium">{album.title}</p>
          <p className="text-xs text-be-muted">
            {album.venue || "No venue"} · {album.gallery_photos.length} photos
          </p>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={() => fileRef.current?.click()}
            disabled={uploading}
            className="rounded-md bg-brand-green px-3 py-1.5 text-sm font-medium text-white hover:bg-brand-green-deep disabled:opacity-50"
          >
            {uploading ? "Uploading…" : "Add photos"}
          </button>
          <button
            onClick={() => onDeleteAlbum(album.id)}
            className="text-xs font-medium text-red-600 hover:text-red-700"
          >
            Delete album
          </button>
        </div>
      </div>
      <div className="mt-3 flex flex-wrap items-center gap-2">
        <label className="text-xs font-medium text-be-muted">Linked event</label>
        <select
          value={album.event_id ?? ""}
          onChange={(e) => onLinkEvent(album.id, e.target.value || null)}
          className="rounded-md border border-be-border bg-be-surface px-2 py-1 text-sm"
        >
          <option value="">Not linked (gallery only)</option>
          {events.map((ev) => (
            <option key={ev.id} value={ev.id}>
              {ev.title}
            </option>
          ))}
        </select>
      </div>

      <input
        ref={fileRef}
        type="file"
        accept="image/*"
        multiple
        onChange={handle}
        className="hidden"
      />
      {album.gallery_photos.length > 0 && (
        <div className="mt-4 grid grid-cols-4 gap-2 sm:grid-cols-6">
          {album.gallery_photos.map((p) => (
            <div key={p.id} className="group relative aspect-square overflow-hidden rounded-md">
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img src={p.url} alt="" className="h-full w-full object-cover" />
              <button
                onClick={() => onDeletePhoto(album.id, p.id)}
                className="absolute right-1 top-1 hidden h-6 w-6 items-center justify-center rounded-full bg-black/70 text-xs text-white group-hover:flex"
                aria-label="Delete photo"
              >
                ×
              </button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
