"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { PageHead } from "../../../_ui/page-head";
import { CoverArt } from "../../../_ui/cover-art";
import { AlbumModal } from "../../../_ui/album-modal";
import { categoryOf, TAB_ORDER, type Category } from "../../../_ui/categories";
import { toast } from "../../../_ui/toast";

type Release = {
  rgMbid: string;
  album: string;
  primaryType: string | null;
  secondaryTypes: string[];
  firstReleaseDate: string | null;
  monitored: boolean;
  have: boolean;
};
type Preview = { artistName: string; followed: boolean; releases: Release[] };

export function PreviewClient({ mbid, initialName }: { mbid: string; initialName: string }) {
  const [data, setData] = useState<Preview | null>(null);
  const [followed, setFollowed] = useState(false);
  const [error, setError] = useState(false);
  const [tab, setTab] = useState<"All" | Category>("Albums");
  const [wanted, setWanted] = useState<Set<string>>(new Set());
  const [open, setOpen] = useState<Release | null>(null);

  const load = useCallback(async () => {
    setError(false);
    const qs = new URLSearchParams({ all: "true" });
    if (initialName) qs.set("name", initialName);
    const res = await fetch(`/api/discover/preview/${mbid}?${qs.toString()}`);
    if (!res.ok) {
      setError(true);
      return;
    }
    const d: Preview = await res.json();
    setData(d);
    setFollowed(d.followed);
  }, [mbid, initialName]);

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

  const name = data?.artistName || initialName;

  async function follow() {
    const res = await fetch("/api/artists", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ mbid, name }),
    });
    if (res.ok || res.status === 409) {
      setFollowed(true);
      toast(`Following ${name}`);
    }
  }

  async function want(r: Release) {
    const res = await fetch("/api/discover/want", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        rgMbid: r.rgMbid,
        artistMbid: mbid,
        artistName: name,
        album: r.album,
        primaryType: r.primaryType,
        secondaryTypes: r.secondaryTypes,
        firstReleaseDate: r.firstReleaseDate,
      }),
    });
    if (res.ok) {
      setWanted((s) => new Set(s).add(r.rgMbid));
      toast(`Added ${r.album}`);
    }
  }

  const counts = useMemo(() => {
    const c: Record<string, number> = {};
    data?.releases.forEach((r) => {
      c[categoryOf(r)] = (c[categoryOf(r)] ?? 0) + 1;
    });
    return c;
  }, [data]);

  function chipFor(r: Release) {
    if (r.have) return <span className="chip done">In library</span>;
    if (r.monitored || wanted.has(r.rgMbid)) return <span className="chip working">Wanted</span>;
    return null;
  }

  if (error)
    return (
      <p className="empty">
        Couldn’t load this artist.{" "}
        <button className="btn sm" onClick={load}>
          Retry
        </button>
      </p>
    );
  if (!data) return <p className="empty">Loading…</p>;

  const tabs: ("All" | Category)[] = ["All", ...TAB_ORDER.filter((t) => counts[t])];
  const visible = tab === "All" ? data.releases : data.releases.filter((r) => categoryOf(r) === tab);

  return (
    <div>
      <PageHead title={name || "Artist"} eyebrow="Preview · discography" />

      <div className="tool-row">
        {followed ? (
          <span className="following">Following</span>
        ) : (
          <button className="btn accent" onClick={follow}>
            Follow
          </button>
        )}
        <a href={`https://musicbrainz.org/artist/${mbid}`} target="_blank" rel="noreferrer">
          MusicBrainz ↗
        </a>
      </div>

      <div className="tabs">
        {tabs.map((t) => (
          <button key={t} className={`tab${tab === t ? " active" : ""}`} onClick={() => setTab(t)}>
            {t}
            <span className="n">{t === "All" ? data.releases.length : counts[t]}</span>
          </button>
        ))}
      </div>

      <ul className="list">
        {visible.map((r) => {
          const owned = r.have || r.monitored || wanted.has(r.rgMbid);
          return (
            <li key={r.rgMbid} className="list-row">
              <div className="main">
                <button className="disco-open" onClick={() => setOpen(r)} aria-label={`Open ${r.album}`}>
                  <CoverArt rgMbid={r.rgMbid} alt={r.album} className="thumb" />
                  <span>
                    <span className="rtitle">{r.album}</span>
                    <span className="rmeta">
                      {r.primaryType ? <span>{r.primaryType}</span> : null}
                      {r.firstReleaseDate ? (
                        <>
                          <span className="dot">·</span>
                          <span>{r.firstReleaseDate.slice(0, 4)}</span>
                        </>
                      ) : null}
                    </span>
                  </span>
                </button>
              </div>
              <div className="actions">
                {chipFor(r)}
                <button className="btn sm" onClick={() => want(r)} disabled={owned}>
                  Want
                </button>
              </div>
            </li>
          );
        })}
      </ul>

      {open ? (
        <AlbumModal
          open
          onClose={() => setOpen(null)}
          album={{
            rgMbid: open.rgMbid,
            album: open.album,
            artist: name,
            year: open.firstReleaseDate?.slice(0, 4) ?? null,
            type: open.primaryType,
            artistMbid: mbid,
          }}
          status={chipFor(open)}
          actions={
            open.have || open.monitored || wanted.has(open.rgMbid) ? null : (
              <button
                className="btn sm"
                onClick={() => {
                  want(open);
                  setOpen(null);
                }}
              >
                Want
              </button>
            )
          }
        />
      ) : null}
    </div>
  );
}
