"use client";

import { useEffect, useState } from "react";
import { SYSTEM_LIST } from "@/lib/systems";
import type { Game } from "@/lib/types";

export function SharedCatalogAdmin() {
  const [shared, setShared] = useState<Game[]>([]);
  const [local, setLocal] = useState<Game[]>([]);
  const [mode, setMode] = useState<"upload" | "promote">("upload");
  const [fromUser, setFromUser] = useState("");
  const [title, setTitle] = useState("");
  const [file, setFile] = useState<File | null>(null);
  const [system, setSystem] = useState("nes");
  const [license, setLicense] = useState("");
  const [source, setSource] = useState("");
  const [author, setAuthor] = useState("");
  const [desc, setDesc] = useState("");
  const [token, setToken] = useState("");
  const [featured, setFeatured] = useState(false);
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState("");
  const [err, setErr] = useState("");

  async function reload() {
    const res = await fetch("/api/contribute");
    const data = (await res.json()) as {
      shared?: Game[];
      local?: Game[];
    };
    setShared(data.shared ?? []);
    setLocal(data.local ?? []);
    if (!fromUser && data.local?.[0]) setFromUser(data.local[0].slug);
  }

  useEffect(() => {
    void reload();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    setBusy(true);
    setErr("");
    setMsg("");
    try {
      if (mode === "upload") {
        if (!file) {
          setErr("Choose a ROM file.");
          return;
        }
        const form = new FormData();
        form.set("file", file);
        if (title.trim()) form.set("title", title.trim());
        form.set("system", system);
        if (license.trim()) form.set("license", license.trim());
        if (source.trim()) form.set("sourceUrl", source.trim());
        if (author.trim()) form.set("author", author.trim());
        if (desc.trim()) form.set("description", desc.trim());
        if (token.trim()) form.set("token", token.trim());
        if (featured) form.set("featured", "true");
        const res = await fetch("/api/contribute", {
          method: "POST",
          body: form,
          headers: token.trim()
            ? { "x-upload-token": token.trim() }
            : undefined,
        });
        const data = (await res.json()) as {
          ok: boolean;
          error?: string;
          message?: string;
        };
        if (!res.ok || !data.ok) {
          setErr(data.error || "Failed to add shared ROM.");
          return;
        }
        setMsg(data.message || "Added.");
        setFile(null);
        setTitle("");
        setDesc("");
        await reload();
        return;
      }

      const res = await fetch("/api/contribute", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...(token.trim() ? { "x-upload-token": token.trim() } : {}),
        },
        body: JSON.stringify({
          fromUser,
          title: title || undefined,
          license: license || undefined,
          sourceUrl: source || undefined,
          author: author || undefined,
          description: desc || undefined,
          featured,
          token: token || undefined,
        }),
      });
      const data = (await res.json()) as {
        ok: boolean;
        error?: string;
        message?: string;
      };
      if (!res.ok || !data.ok) {
        setErr(data.error || "Failed to promote.");
        return;
      }
      setMsg(data.message || "Promoted.");
      await reload();
    } catch (e) {
      setErr(e instanceof Error ? e.message : "Request failed");
    } finally {
      setBusy(false);
    }
  }

  return (
    <section className="mt-12">
      <h2 className="font-display text-sm tracking-wider uppercase">
        Shared catalog
      </h2>
      <p className="mt-2 max-w-2xl text-sm text-muted">
        Public uploads also live at{" "}
        <a href="/contribute" className="text-accent underline-offset-2 hover:underline">
          /contribute
        </a>
        . Needs persistent disk on the host. No legal filter — uploaders are
        responsible for what they share.
      </p>

      <div className="mt-4 grid gap-3 text-sm sm:grid-cols-2">
        <div className="settings-panel">
          <p className="settings-label">Shared playable ({shared.length})</p>
          <ul className="mt-2 max-h-40 space-y-1 overflow-auto text-muted">
            {shared.slice(0, 40).map((g) => (
              <li key={g.slug}>
                {g.system}: {g.title}
              </li>
            ))}
          </ul>
        </div>
        <div className="settings-panel">
          <p className="settings-label">Local only ({local.length})</p>
          <ul className="mt-2 max-h-40 space-y-1 overflow-auto text-muted">
            {local.length === 0 ? (
              <li>None</li>
            ) : (
              local.map((g) => (
                <li key={g.slug}>
                  {g.system}: {g.title}
                </li>
              ))
            )}
          </ul>
        </div>
      </div>

      <div className="mt-4 max-w-md">
        <label className="block text-sm">
          <span className="settings-label">Upload token (for scan / writes)</span>
          <input
            className="settings-input"
            type="password"
            autoComplete="off"
            value={token}
            onChange={(e) => setToken(e.target.value)}
            placeholder="HOLLOWCADE_UPLOAD_TOKEN"
          />
        </label>
      </div>

      <div className="mt-4 flex flex-wrap gap-2">
        <button
          type="button"
          className="btn-ghost"
          disabled={busy}
          onClick={() => {
            void (async () => {
              setBusy(true);
              setErr("");
              setMsg("");
              try {
                const res = await fetch("/api/catalog/scan", {
                  method: "POST",
                  headers: token.trim()
                    ? { "x-upload-token": token.trim() }
                    : undefined,
                });
                const data = (await res.json()) as {
                  ok: boolean;
                  error?: string;
                  message?: string;
                  added?: number;
                };
                if (!res.ok || !data.ok) {
                  setErr(data.error || "Scan failed.");
                  return;
                }
                setMsg(data.message || `Added ${data.added ?? 0}.`);
                await reload();
              } catch (e) {
                setErr(e instanceof Error ? e.message : "Scan failed");
              } finally {
                setBusy(false);
              }
            })();
          }}
        >
          Rescan public/roms → local catalog
        </button>
      </div>

      <form
        className="settings-panel mt-6 space-y-4"
        onSubmit={(e) => void submit(e)}
      >
        <div className="flex flex-wrap gap-2">
          <button
            type="button"
            className={mode === "upload" ? "btn-primary" : "btn-ghost"}
            onClick={() => setMode("upload")}
          >
            Upload file
          </button>
          <button
            type="button"
            className={mode === "promote" ? "btn-primary" : "btn-ghost"}
            onClick={() => setMode("promote")}
            disabled={local.length === 0}
          >
            Promote local entry
          </button>
        </div>

        {mode === "upload" ? (
          <>
            <label className="block text-sm">
              <span className="settings-label">ROM file</span>
              <input
                type="file"
                className="settings-input"
                onChange={(e) => setFile(e.target.files?.[0] ?? null)}
                required={mode === "upload"}
              />
            </label>
            <label className="block text-sm">
              <span className="settings-label">System</span>
              <select
                className="settings-input"
                value={system}
                onChange={(e) => setSystem(e.target.value)}
              >
                {SYSTEM_LIST.map((s) => (
                  <option key={s.id} value={s.id}>
                    {s.shortName} — {s.name}
                  </option>
                ))}
              </select>
            </label>
          </>
        ) : (
          <label className="block text-sm">
            <span className="settings-label">Local entry to promote</span>
            <select
              className="settings-input"
              value={fromUser}
              onChange={(e) => setFromUser(e.target.value)}
              required
            >
              {local.map((g) => (
                <option key={g.slug} value={g.slug}>
                  {g.title} ({g.system})
                </option>
              ))}
            </select>
          </label>
        )}

        <label className="block text-sm">
          <span className="settings-label">Title (optional)</span>
          <input
            className="settings-input"
            value={title}
            onChange={(e) => setTitle(e.target.value)}
          />
        </label>
        <label className="block text-sm">
          <span className="settings-label">License (optional)</span>
          <input
            className="settings-input"
            value={license}
            onChange={(e) => setLicense(e.target.value)}
          />
        </label>
        <label className="block text-sm">
          <span className="settings-label">Source URL (optional)</span>
          <input
            className="settings-input"
            value={source}
            onChange={(e) => setSource(e.target.value)}
          />
        </label>
        <label className="block text-sm">
          <span className="settings-label">Author (optional)</span>
          <input
            className="settings-input"
            value={author}
            onChange={(e) => setAuthor(e.target.value)}
          />
        </label>
        <label className="block text-sm">
          <span className="settings-label">Description (optional)</span>
          <textarea
            className="settings-input min-h-[4rem]"
            value={desc}
            onChange={(e) => setDesc(e.target.value)}
          />
        </label>
        <label className="block text-sm">
          <span className="settings-label">Upload token (if required)</span>
          <input
            className="settings-input"
            type="password"
            autoComplete="off"
            value={token}
            onChange={(e) => setToken(e.target.value)}
          />
        </label>
        <label className="flex items-center gap-2 text-sm">
          <input
            type="checkbox"
            checked={featured}
            onChange={(e) => setFeatured(e.target.checked)}
          />
          Featured
        </label>

        <button type="submit" className="btn-primary" disabled={busy}>
          {busy ? "Working…" : "Add to shared catalog"}
        </button>

        {err && (
          <p className="text-sm text-accent-hot whitespace-pre-wrap">{err}</p>
        )}
        {msg && <p className="text-sm text-amber whitespace-pre-wrap">{msg}</p>}
      </form>
    </section>
  );
}
