import { useCallback, useEffect, useRef, useState } from "react";
import { apiGet, apiPost, apiPostImage } from "../../api";
import { PageHead, Empty, Loading } from "../../components/ui";
import { IconCheck, IconLayers, IconSearch, IconWand } from "../../components/icons";
import { useToast } from "../../lib/toast";

interface Collection {
  id: string;
  name: string;
  child_count: number;
  poster_url: string | null;
}

interface Opts {
  target_type: string;
  text: string;
  text_color: string;
  text_align: string;
  text_position: string;
  text_scale: number;
  darkness: number;
}

const DEFAULTS: Opts = {
  target_type: "Thumb",
  text: "",
  text_color: "#FFFFFF",
  text_align: "center",
  text_position: "bottom",
  text_scale: 1.0,
  darkness: 0.18,
};

export default function Collections() {
  const toast = useToast();
  const [query, setQuery] = useState("");
  const [list, setList] = useState<Collection[]>([]);
  const [loading, setLoading] = useState(true);
  const [selected, setSelected] = useState<Collection | null>(null);
  const [opts, setOpts] = useState<Opts>(DEFAULTS);
  const [preview, setPreview] = useState<string | null>(null);
  const [rendering, setRendering] = useState(false);
  const [applying, setApplying] = useState(false);
  const debounceRef = useRef<number>();

  const set = <K extends keyof Opts>(k: K, v: Opts[K]) => setOpts((o) => ({ ...o, [k]: v }));

  const load = useCallback(() => {
    setLoading(true);
    apiGet<{ items: Collection[] }>(`/api/collections?q=${encodeURIComponent(query.trim())}&limit=60`)
      .then((d) => setList(d.items))
      .catch((e) => toast(e.message, "err"))
      .finally(() => setLoading(false));
  }, [query, toast]);

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

  function select(c: Collection) {
    setSelected(c);
    setPreview(null);
    setOpts({ ...DEFAULTS, text: c.name });
  }

  const generate = useCallback(async () => {
    if (!selected) return;
    setRendering(true);
    try {
      const { url } = await apiPostImage("/api/collections/generate", { item_id: selected.id, ...opts });
      setPreview((p) => {
        if (p) URL.revokeObjectURL(p);
        return url;
      });
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setRendering(false);
    }
  }, [selected, opts, toast]);

  useEffect(() => {
    if (!selected) return;
    window.clearTimeout(debounceRef.current);
    debounceRef.current = window.setTimeout(generate, 350);
    return () => window.clearTimeout(debounceRef.current);
  }, [selected, opts]); // eslint-disable-line react-hooks/exhaustive-deps

  async function apply() {
    if (!selected) return;
    setApplying(true);
    try {
      await apiPost("/api/collections/apply", { item_id: selected.id, ...opts });
      toast(`Applied ${opts.target_type} to ${selected.name}`, "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setApplying(false);
    }
  }

  return (
    <>
      <PageHead title="Collection Art">Generate cover artwork for your Emby collections with custom titling.</PageHead>

      <div className="workbench">
        <div className="panel" style={{ display: "flex", flexDirection: "column", maxHeight: "calc(100vh - 200px)" }}>
          <div style={{ padding: 14, borderBottom: "1px solid var(--border)" }}>
            <form
              className="search-inner"
              onSubmit={(e) => {
                e.preventDefault();
                load();
              }}
            >
              <IconSearch />
              <input className="input" placeholder="Search collections…" value={query} onChange={(e) => setQuery(e.target.value)} />
            </form>
          </div>
          <div style={{ overflowY: "auto", padding: 8 }}>
            {loading ? (
              <Loading />
            ) : !list.length ? (
              <Empty icon={<IconLayers />}>No collections found.</Empty>
            ) : (
              list.map((c) => (
                <div key={c.id} className={`result-item ${selected?.id === c.id ? "active" : ""}`} onClick={() => select(c)}>
                  {c.poster_url ? <img className="result-poster" src={c.poster_url} loading="lazy" alt="" /> : <div className="result-poster" />}
                  <div className="grow">
                    <div className="result-name">{c.name}</div>
                    <div className="result-sub">{c.child_count} items</div>
                  </div>
                </div>
              ))
            )}
          </div>
        </div>

        <div className="preview-shell">
          {!selected ? (
            <Empty icon={<IconLayers />}>Select a collection to design its artwork.</Empty>
          ) : (
            <>
              <div className="preview-frame" style={{ aspectRatio: opts.target_type === "Primary" ? "2 / 3" : "16 / 9", maxWidth: opts.target_type === "Primary" ? 360 : "100%" }}>
                {preview ? <img src={preview} alt="preview" /> : <Loading />}
              </div>
              <div className="row" style={{ width: "100%" }}>
                <button className="btn grow" onClick={generate} disabled={rendering}>
                  <IconWand /> Regenerate
                </button>
                <button className="btn btn-primary grow" onClick={apply} disabled={applying || !preview}>
                  {applying ? <span className="spinner" /> : <IconCheck />} Apply
                </button>
              </div>
            </>
          )}
        </div>

        <div className="panel scroll-col" style={{ maxHeight: "calc(100vh - 200px)" }}>
          <div className="panel-head">
            <h3>Controls</h3>
          </div>
          <div className="panel-body col" style={{ gap: 16 }}>
            {!selected ? (
              <p className="hint">Pick a collection first.</p>
            ) : (
              <>
                <div className="field">
                  <label className="field-label">Target image</label>
                  <div className="seg">
                    <button className={`seg-btn ${opts.target_type === "Thumb" ? "active" : ""}`} onClick={() => set("target_type", "Thumb")}>
                      Thumb
                    </button>
                    <button className={`seg-btn ${opts.target_type === "Primary" ? "active" : ""}`} onClick={() => set("target_type", "Primary")}>
                      Primary
                    </button>
                  </div>
                </div>
                <div className="field">
                  <label className="field-label">Title text</label>
                  <input className="input" value={opts.text} onChange={(e) => set("text", e.target.value)} />
                </div>
                <div className="field">
                  <label className="field-label">Text align</label>
                  <div className="seg">
                    {["left", "center", "right"].map((a) => (
                      <button key={a} className={`seg-btn ${opts.text_align === a ? "active" : ""}`} onClick={() => set("text_align", a)}>
                        {a}
                      </button>
                    ))}
                  </div>
                </div>
                <div className="field">
                  <label className="field-label">Text position</label>
                  <div className="seg">
                    {["top", "center", "bottom"].map((p) => (
                      <button key={p} className={`seg-btn ${opts.text_position === p ? "active" : ""}`} onClick={() => set("text_position", p)}>
                        {p}
                      </button>
                    ))}
                  </div>
                </div>
                <div className="field">
                  <label className="field-label">
                    Text scale <span className="mono">{opts.text_scale.toFixed(2)}×</span>
                  </label>
                  <input type="range" min={0.65} max={1.8} step={0.05} value={opts.text_scale} onChange={(e) => set("text_scale", +e.target.value)} />
                </div>
                <div className="field">
                  <label className="field-label">
                    Darkness <span className="mono">{Math.round(opts.darkness * 100)}%</span>
                  </label>
                  <input type="range" min={0} max={0.85} step={0.05} value={opts.darkness} onChange={(e) => set("darkness", +e.target.value)} />
                </div>
                <div className="field">
                  <label className="field-label">Text color</label>
                  <div className="row">
                    <input type="color" value={opts.text_color} onChange={(e) => set("text_color", e.target.value)} />
                    <input className="input grow" value={opts.text_color} onChange={(e) => set("text_color", e.target.value)} />
                  </div>
                </div>
              </>
            )}
          </div>
        </div>
      </div>
    </>
  );
}
