"use client";

import { FormEvent, useEffect, useMemo, useState } from "react";
import Combobox from "../components/Combobox";

type LibraryImage = {
  id: string;
  name: string;
  tags: string;
  url: string;
  byteSize: number;
};

function splitTags(value: string) {
  return value
    .split(",")
    .map((entry) => entry.trim())
    .filter(Boolean);
}

export default function LibraryManager() {
  const [images, setImages] = useState<LibraryImage[] | null>(null);
  const [name, setName] = useState("");
  const [tags, setTags] = useState("");
  const [filter, setFilter] = useState("");
  const [file, setFile] = useState<File | null>(null);
  const [fileKey, setFileKey] = useState(0);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function load() {
    const response = await fetch("/api/library", { cache: "no-store", credentials: "same-origin" });
    const payload = await response.json().catch(() => null);
    if (!response.ok || !payload?.ok) {
      setError(payload?.error?.message ?? "Biblioteka nije dostupna.");
      setImages([]);
      return;
    }
    setImages(payload.images);
  }

  useEffect(() => { void load(); }, []);

  // Both dropdowns are built from what is already in the library, so a tag is
  // spelled the same way the second time it is used.
  const knownNames = useMemo(
    () => [...new Set((images ?? []).map((image) => image.name.trim()).filter(Boolean))]
      .sort((left, right) => left.localeCompare(right, "sr-Latn-RS")),
    [images],
  );
  const knownTags = useMemo(
    () => [...new Set((images ?? []).flatMap((image) => splitTags(image.tags)))]
      .sort((left, right) => left.localeCompare(right, "sr-Latn-RS")),
    [images],
  );

  const visible = useMemo(() => {
    const needle = filter.trim().toLowerCase();
    if (!needle) return images ?? [];
    return (images ?? []).filter((image) =>
      `${image.name} ${image.tags}`.toLowerCase().includes(needle),
    );
  }, [filter, images]);

  async function upload(event: FormEvent) {
    event.preventDefault();
    if (!file) { setError("Izaberite fotografiju."); return; }
    setBusy(true);
    setError(null);
    const form = new FormData();
    form.append("file", file);
    form.append("name", name.trim());
    // A trailing comma is left behind whenever a tag is picked from the list.
    form.append("tags", splitTags(tags).join(", "));
    const response = await fetch("/api/library", { method: "POST", credentials: "same-origin", body: form });
    const payload = await response.json().catch(() => null);
    setBusy(false);
    if (!response.ok || !payload?.ok) {
      setError(payload?.error?.message ?? "Otpremanje nije uspelo.");
      return;
    }
    setName(""); setTags(""); setFile(null);
    // Remount the file input so the previous filename stops showing.
    setFileKey((current) => current + 1);
    await load();
  }

  async function remove(image: LibraryImage) {
    setBusy(true);
    setError(null);
    const response = await fetch("/api/library", {
      method: "DELETE",
      credentials: "same-origin",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ id: image.id }),
    });
    const payload = await response.json().catch(() => null);
    setBusy(false);
    if (!response.ok || !payload?.ok) {
      setError(payload?.error?.message ?? "Brisanje nije uspelo.");
      return;
    }
    await load();
  }

  return <section className="library-manager">
    <header>
      <h2>Zajednička biblioteka fotografija</h2>
      <p>
        Standardni proizvodi koji izgledaju isto u svakom restoranu — Heineken,
        Coca-Cola, Jelen. Otpremite ih jednom, a svi restorani ih biraju iz
        menija. Restoran koji izabere fotografiju dobija svoju kopiju, pa
        kasnije brisanje odavde ne kvari nikome meni.
      </p>
    </header>

    <form className="library-upload" onSubmit={upload}>
      <Combobox
        label="Naziv proizvoda"
        value={name}
        options={knownNames}
        onChange={setName}
        maxLength={80}
        required
        placeholder="npr. Heineken 0,33"
      />
      <Combobox
        label="Oznake za pretragu"
        value={tags}
        options={knownTags}
        onChange={setTags}
        maxLength={160}
        multi
        placeholder="pivo, flaša, svetlo"
        hint="Više oznaka razdvojite zapetom. Lista nudi već korišćene oznake."
      />
      <label>Fotografija
        <input key={fileKey} type="file" accept="image/png,image/jpeg,image/webp" required
          onChange={(event) => setFile(event.target.files?.[0] ?? null)} />
      </label>
      <button className="primary-button" type="submit" disabled={busy}>{busy ? "Otpremanje…" : "＋ Dodaj u biblioteku"}</button>
    </form>
    {error && <div className="auth-error" role="alert">{error}</div>}

    {images !== null && images.length > 0 && <Combobox
      label="Pretraga biblioteke"
      value={filter}
      options={[...knownNames, ...knownTags]}
      onChange={setFilter}
      maxLength={60}
      placeholder="npr. Heineken, pivo"
    />}

    {images === null
      ? <p className="platform-loading">Učitavamo biblioteku…</p>
      : visible.length
        ? <div className="library-grid manage">{visible.map((image) => <div key={image.id}>
            <img src={image.url} alt={image.name} loading="lazy" />
            <strong>{image.name}</strong>
            {image.tags && <small>{image.tags}</small>}
            <button type="button" className="danger-button" disabled={busy} onClick={() => void remove(image)}>Obriši</button>
          </div>)}</div>
        : <p className="platform-loading">{images.length ? "Nema fotografije za tu pretragu." : "Biblioteka je prazna. Dodajte prvu fotografiju iznad."}</p>}
  </section>;
}
