"use client";

import { useRef, useState } from "react";
import type { FavoriteGame } from "@/lib/integrations/types";

// Searchable favorite-games picker. Mirrors the console picker UX, but results
// come from the server (Steam store search via /games/search) since the catalog
// is far too large to bundle. Typing debounces a fetch; clicking a result adds
// it as a chip with its cover art. Free-text entry is always available for
// console/retro titles the search doesn't surface.

type Result = { name: string; image?: string; url?: string };

function Cover({ image }: { image?: string }) {
  if (!image) return <span className="rb-pick-cover rb-pick-cover-empty" aria-hidden>🎲</span>;
  // eslint-disable-next-line @next/next/no-img-element
  return <img className="rb-pick-cover" src={image} alt="" loading="lazy" />;
}

export default function GamePicker({
  name,
  initial,
}: {
  name: string;
  initial: FavoriteGame[];
}) {
  const [items, setItems] = useState<FavoriteGame[]>(initial);
  const [query, setQuery] = useState("");
  const [results, setResults] = useState<Result[]>([]);
  const [loading, setLoading] = useState(false);
  const [open, setOpen] = useState(false);
  const abortRef = useRef<AbortController | null>(null);
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Search is event-driven (no effect): each keystroke reschedules a debounced
  // fetch against the admin-only Steam search route, cancelling any in-flight
  // request so only the latest query's results land.
  function onQueryChange(next: string) {
    setQuery(next);
    setOpen(true);
    if (timerRef.current) clearTimeout(timerRef.current);
    const q = next.trim();
    if (q.length < 2) {
      abortRef.current?.abort();
      setResults([]);
      setLoading(false);
      return;
    }
    setLoading(true);
    timerRef.current = setTimeout(async () => {
      abortRef.current?.abort();
      const ctrl = new AbortController();
      abortRef.current = ctrl;
      try {
        const res = await fetch(
          `/admin/integrations/games/search?q=${encodeURIComponent(q)}`,
          { signal: ctrl.signal }
        );
        const json = (await res.json()) as { games?: Result[] };
        setResults(json.games ?? []);
      } catch {
        // aborted or network error — leave prior results, drop the spinner
      } finally {
        setLoading(false);
      }
    }, 300);
  }

  function add(g: Result) {
    setItems((prev) => [...prev, { name: g.name, image: g.image, url: g.url }]);
    setQuery("");
    setResults([]);
    setOpen(false);
  }

  function addFreeform() {
    const label = query.trim();
    if (!label) return;
    setItems((prev) => [...prev, { name: label }]);
    setQuery("");
    setResults([]);
    setOpen(false);
  }

  function remove(idx: number) {
    setItems((prev) => prev.filter((_, i) => i !== idx));
  }

  function setNote(idx: number, note: string) {
    setItems((prev) => prev.map((it, i) => (i === idx ? { ...it, note } : it)));
  }

  return (
    <div className="rb-picker">
      <input type="hidden" name={name} value={JSON.stringify(items)} />

      <div className="rb-pick-search">
        <input
          type="text"
          value={query}
          placeholder="Search games — e.g. Chrono Trigger, Hollow Knight…"
          autoComplete="off"
          onChange={(e) => onQueryChange(e.target.value)}
          onFocus={() => setOpen(true)}
          onBlur={() => setTimeout(() => setOpen(false), 150)}
          onKeyDown={(e) => {
            if (e.key === "Enter") {
              e.preventDefault();
              if (results[0]) add(results[0]);
              else addFreeform();
            }
          }}
        />
        {open && query.trim().length >= 2 && (
          <ul className="rb-pick-suggest">
            {loading && results.length === 0 && (
              <li className="rb-pick-status">Searching…</li>
            )}
            {results.map((g, i) => (
              <li key={`${g.url ?? g.name}-${i}`}>
                <button type="button" onMouseDown={(e) => e.preventDefault()} onClick={() => add(g)}>
                  <Cover image={g.image} />
                  <span className="rb-pick-suggest-name">{g.name}</span>
                </button>
              </li>
            ))}
            <li>
              <button
                type="button"
                className="rb-pick-freeform"
                onMouseDown={(e) => e.preventDefault()}
                onClick={addFreeform}
              >
                ＋ Add “{query.trim()}” as custom
              </button>
            </li>
          </ul>
        )}
      </div>

      {items.length > 0 && (
        <ul className="rb-pick-list">
          {items.map((it, i) => (
            <li key={`${it.url ?? it.name}-${i}`} className="rb-pick-chip">
              <Cover image={it.image} />
              <span className="rb-pick-chip-name">{it.name}</span>
              <input
                className="rb-pick-chip-note"
                type="text"
                value={it.note ?? ""}
                placeholder="note (optional)"
                onChange={(e) => setNote(i, e.target.value)}
              />
              <button
                type="button"
                className="rb-pick-remove"
                aria-label={`Remove ${it.name}`}
                onClick={() => remove(i)}
              >
                ✕
              </button>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}
