"use client";

import { useEffect, useState } from "react";
import type { EventPhoto } from "@db/queries/gallery-db";

// Forces a real download even for cross-origin storage URLs by fetching the
// blob first; falls back to opening the image if CORS blocks the fetch.
async function downloadPhoto(url: string, filename: string) {
  try {
    const res = await fetch(url, { mode: "cors" });
    if (!res.ok) throw new Error(String(res.status));
    const blob = await res.blob();
    const objectUrl = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = objectUrl;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(objectUrl);
  } catch {
    window.open(url, "_blank", "noopener");
  }
}

function Credit({ photo, className }: { photo: EventPhoto; className?: string }) {
  if (!photo.creditName) return null;
  const label = `📷 ${photo.creditName}`;
  return photo.creditUrl ? (
    <a
      href={photo.creditUrl}
      target="_blank"
      rel="noopener noreferrer"
      onClick={(e) => e.stopPropagation()}
      className={`hover:text-white hover:underline ${className ?? ""}`}
    >
      {label}
    </a>
  ) : (
    <span className={className}>{label}</span>
  );
}

export default function EventGallery({
  photos,
  title,
  eventId,
}: {
  photos: EventPhoto[];
  title: string;
  eventId: string;
}) {
  const [active, setActive] = useState<number | null>(null);

  const close = () => setActive(null);
  const prev = () => setActive((i) => (i === null ? i : (i - 1 + photos.length) % photos.length));
  const next = () => setActive((i) => (i === null ? i : (i + 1) % photos.length));

  const fileName = (i: number) => `${title.replace(/[^a-z0-9]+/gi, "-").toLowerCase()}-${i + 1}.jpg`;

  useEffect(() => {
    if (active === null) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") close();
      if (e.key === "ArrowLeft") prev();
      if (e.key === "ArrowRight") next();
    };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [active]); // eslint-disable-line react-hooks/exhaustive-deps

  return (
    <>
      <div className="mb-4 flex justify-end">
        <a
          href={`/api/events/${eventId}/photos.zip`}
          className="inline-flex items-center gap-2 rounded-full border border-line bg-panel px-4 py-2 text-sm font-semibold text-white hover:border-brand-green"
        >
          <DownloadIcon /> Download all ({photos.length})
        </a>
      </div>

      <div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
        {photos.map((photo, i) => (
          <div
            key={photo.id}
            className="group relative aspect-square overflow-hidden rounded-xl border border-line bg-panel"
          >
            <button onClick={() => setActive(i)} className="block h-full w-full" aria-label="View photo">
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={photo.url}
                alt={`${title} photo ${i + 1}`}
                loading="lazy"
                className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
              />
            </button>

            {/* Per-photo download */}
            <button
              onClick={() => downloadPhoto(photo.url, fileName(i))}
              className="absolute right-2 top-2 hidden h-8 w-8 items-center justify-center rounded-full bg-black/65 text-white backdrop-blur hover:bg-black/85 group-hover:flex"
              aria-label="Download photo"
              title="Download"
            >
              <DownloadIcon />
            </button>

            {photo.creditName && (
              <div className="pointer-events-none absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/70 to-transparent p-2 pt-6 opacity-0 transition-opacity group-hover:opacity-100">
                <Credit photo={photo} className="pointer-events-auto text-[11px] font-medium text-white/85" />
              </div>
            )}
          </div>
        ))}
      </div>

      {active !== null && (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center bg-black/90 p-4"
          onClick={close}
        >
          <button
            className="absolute right-4 top-4 text-3xl leading-none text-white/70 hover:text-white"
            onClick={close}
            aria-label="Close"
          >
            ×
          </button>
          <button
            className="absolute left-4 px-3 text-4xl text-white/70 hover:text-white"
            onClick={(e) => {
              e.stopPropagation();
              prev();
            }}
            aria-label="Previous"
          >
            ‹
          </button>

          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img
            src={photos[active].url}
            alt={`${title} photo ${active + 1}`}
            className="max-h-[85vh] max-w-[90vw] rounded-lg object-contain"
            onClick={(e) => e.stopPropagation()}
          />

          <button
            className="absolute right-4 px-3 text-4xl text-white/70 hover:text-white"
            onClick={(e) => {
              e.stopPropagation();
              next();
            }}
            aria-label="Next"
          >
            ›
          </button>

          <div
            className="absolute inset-x-0 bottom-4 flex items-center justify-center gap-4 text-sm text-white/70"
            onClick={(e) => e.stopPropagation()}
          >
            <Credit photo={photos[active]} className="text-white/80" />
            <span>
              {active + 1} / {photos.length}
            </span>
            <button
              onClick={() => downloadPhoto(photos[active].url, fileName(active))}
              className="inline-flex items-center gap-1.5 rounded-full bg-white/15 px-3 py-1.5 font-medium text-white hover:bg-white/25"
            >
              <DownloadIcon /> Download
            </button>
          </div>
        </div>
      )}
    </>
  );
}

function DownloadIcon() {
  return (
    <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" aria-hidden="true">
      <path
        d="M12 3v12m0 0l-4-4m4 4l4-4M5 21h14"
        stroke="currentColor"
        strokeWidth="2"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}
