"use client";

import { useEffect, useId, useRef, useState } from "react";
import { Button } from "@/components/ui";
import { inputClass } from "@/components/ui/form";

interface Row { id: string; filename: string; altText: string | null; mimeType: string; isPrivate: boolean }

/** Image picker over the site's media library. Private assets are never offered (they can't be placed on pages). */
export function MediaPicker({ siteId, value, onChange, disabled, label }: { siteId: string; value: string | null; onChange: (id: string | null) => void; disabled?: boolean; label: string }) {
  const dialog = useRef<HTMLDialogElement>(null);
  const [q, setQ] = useState("");
  const [rows, setRows] = useState<Row[] | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [open, setOpen] = useState(false);
  const titleId = useId();

  useEffect(() => {
    if (!open) return;
    const controller = new AbortController();
    const timer = setTimeout(async () => {
      try {
        setError(null);
        const params = new URLSearchParams({ siteId, kind: "image" });
        if (q.trim()) params.set("q", q.trim());
        const res = await fetch(`/api/media?${params}`, { signal: controller.signal });
        if (!res.ok) throw new Error("Could not load the media library");
        const json = (await res.json()) as { rows: Row[] };
        setRows(json.rows.filter((r) => !r.isPrivate));
      } catch (e) {
        if ((e as Error).name !== "AbortError") setError((e as Error).message);
      }
    }, 200);
    return () => {
      clearTimeout(timer);
      controller.abort();
    };
  }, [open, q, siteId]);

  function show() {
    setOpen(true);
    dialog.current?.showModal();
  }
  function hide() {
    dialog.current?.close();
    setOpen(false);
  }

  return (
    <div className="flex items-center gap-3">
      {value ? (
        // eslint-disable-next-line @next/next/no-img-element -- own media route
        <img src={`/api/media/${value}`} alt="" className="h-12 w-12 rounded border border-border object-cover" />
      ) : (
        <div className="grid h-12 w-12 place-items-center rounded border border-dashed border-border text-xs text-muted-foreground">None</div>
      )}
      <Button variant="secondary" onClick={show} disabled={disabled} aria-label={`${value ? "Change" : "Choose"} ${label}`}>{value ? "Change" : "Choose"}</Button>
      {value && !disabled ? <Button variant="ghost" onClick={() => onChange(null)}>Remove</Button> : null}
      <dialog ref={dialog} onClose={() => setOpen(false)} aria-labelledby={titleId} className="m-auto w-[min(48rem,92vw)] rounded-lg border border-border bg-card p-4 text-foreground backdrop:bg-black/40">
        <div className="mb-3 flex items-center justify-between gap-3">
          <h2 id={titleId} className="text-sm font-semibold">Choose an image</h2>
          <Button variant="ghost" onClick={hide}>Close</Button>
        </div>
        <input type="search" aria-label="Search images" placeholder="Search by name or alt text" value={q} onChange={(e) => setQ(e.target.value)} className={inputClass} />
        {error ? <p role="alert" className="mt-3 text-sm text-danger">{error}</p> : null}
        {rows === null && !error ? <p className="mt-3 text-sm text-muted-foreground">Loading…</p> : null}
        {rows && rows.length === 0 ? <p className="mt-3 text-sm text-muted-foreground">No images found. Upload images in the media library first.</p> : null}
        <ul className="mt-3 grid max-h-[55vh] grid-cols-3 gap-3 overflow-y-auto sm:grid-cols-4">
          {rows?.map((r) => (
            <li key={r.id}>
              <button type="button" onClick={() => { onChange(r.id); hide(); }} className="block w-full overflow-hidden rounded border border-border text-left hover:border-primary focus-visible:border-primary">
                {/* eslint-disable-next-line @next/next/no-img-element -- own media route */}
                <img src={`/api/media/${r.id}`} alt={r.altText ?? ""} loading="lazy" className="aspect-square w-full object-cover" />
                <span className="block truncate px-1.5 py-1 text-xs">{r.filename}</span>
                {!r.altText ? <span className="block px-1.5 pb-1 text-[10px] text-warning">No alt text</span> : null}
              </button>
            </li>
          ))}
        </ul>
      </dialog>
    </div>
  );
}
