import { useState } from "react";
import { qk } from "../lib/queryKeys";
import { useTranslation } from "react-i18next";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { Check, Minus, Plus } from "lucide-react";
import { api, type PlexPlaylist } from "../lib/api";
import { useScrollFade } from "../lib/useScrollFade";
import Modal from "./Modal";

// What we're adding: a single leaf (movie/episode) or a whole group (a season or an entire show, as a
// set of episode rating_keys). Groups get a tri-state (none / some / all) per playlist.
export type PlexAddTarget =
  | { kind: "single"; ratingKey: string; title: string }
  | { kind: "group"; ratingKeys: string[]; title: string };

// "Add to playlist" dialog — per-user (every user has their own playlists). Opened from the movie info
// page (single) and the show page (single episode / whole season / whole show). Lists my playlists with
// an in/out (or partial) state and a field to create a new one seeded with the target.
export default function PlexPlaylistAdd({
  target,
  onClose,
}: {
  target: PlexAddTarget;
  onClose: () => void;
}) {
  const { t } = useTranslation();
  const fade = useScrollFade();
  const qc = useQueryClient();
  const [newName, setNewName] = useState("");
  const [busy, setBusy] = useState(false);
  // Optimistic per-playlist in-count override (0..size), so a toggle reflects instantly.
  const [override, setOverride] = useState<Map<number, number>>(new Map());

  const isGroup = target.kind === "group";
  const size = isGroup ? new Set(target.ratingKeys).size : 1;

  const listQ = useQuery({
    queryKey: isGroup
      ? qk.plexPlaylists("group", target.ratingKeys)
      : qk.plexPlaylists("contains", target.ratingKey),
    queryFn: () =>
      isGroup
        ? api.plexPlaylists(undefined, target.ratingKeys)
        : api.plexPlaylists(target.ratingKey),
  });
  const playlists = listQ.data?.playlists ?? [];
  const refresh = () => qc.invalidateQueries({ queryKey: qk.plexPlaylists() });

  // How many of the target a playlist currently holds (0..size).
  function inCount(p: PlexPlaylist): number {
    const o = override.get(p.id);
    if (o !== undefined) return o;
    return isGroup ? (p.group_in ?? 0) : p.has_item ? 1 : 0;
  }

  async function toggle(p: PlexPlaylist) {
    if (busy) return;
    setBusy(true);
    const allIn = inCount(p) >= size;
    try {
      if (isGroup) {
        if (allIn) await api.plexPlaylistRemoveBulk(p.id, target.ratingKeys);
        else await api.plexPlaylistAddBulk(p.id, target.ratingKeys);
      } else {
        if (allIn) await api.plexPlaylistRemoveItem(p.id, target.ratingKey);
        else await api.plexPlaylistAddItem(p.id, target.ratingKey);
      }
      setOverride((m) => new Map(m).set(p.id, allIn ? 0 : size));
      refresh();
    } finally {
      setBusy(false);
    }
  }

  async function createNew() {
    const title = newName.trim();
    if (!title || busy) return;
    setBusy(true);
    try {
      if (isGroup) {
        const pl = await api.plexCreatePlaylist(title);
        await api.plexPlaylistAddBulk(pl.id, target.ratingKeys);
        setOverride((m) => new Map(m).set(pl.id, size));
      } else {
        const pl = await api.plexCreatePlaylist(title, target.ratingKey);
        setOverride((m) => new Map(m).set(pl.id, 1));
      }
      setNewName("");
      refresh();
    } finally {
      setBusy(false);
    }
  }

  return (
    <Modal title={t("plex.playlistAdd.title", { title: target.title })} onClose={onClose}>
      <div className="mb-3 flex gap-2">
        <input
          value={newName}
          onChange={(e) => setNewName(e.target.value)}
          onKeyDown={(e) => e.key === "Enter" && createNew()}
          placeholder={t("plex.playlistAdd.newPlaceholder")}
          className="glass-card min-w-0 flex-1 rounded-lg px-3 py-2 text-sm outline-none focus:border-accent"
        />
        <button
          onClick={createNew}
          disabled={!newName.trim() || busy}
          className="glass-card glass-hover inline-flex shrink-0 items-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium disabled:opacity-50"
        >
          <Plus className="h-4 w-4" />
          {t("plex.playlistAdd.create")}
        </button>
      </div>

      <div
        ref={fade.ref}
        style={fade.style}
        className="max-h-80 space-y-1 overflow-y-auto no-scrollbar"
      >
        {listQ.isLoading ? (
          <p className="py-4 text-center text-sm text-muted">{t("plex.loading")}</p>
        ) : playlists.length === 0 ? (
          <p className="py-4 text-center text-sm text-muted">{t("plex.playlistAdd.none")}</p>
        ) : (
          playlists.map((p) => {
            const n = inCount(p);
            const all = n >= size;
            const partial = n > 0 && n < size;
            return (
              <button
                key={p.id}
                onClick={() => toggle(p)}
                disabled={busy}
                className={`glass-card flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-left text-sm disabled:opacity-50 ${
                  all ? "text-accent" : ""
                }`}
              >
                <span
                  className={`grid h-5 w-5 shrink-0 place-items-center rounded border ${
                    all || partial ? "border-accent bg-accent/20" : "border-border"
                  }`}
                >
                  {all ? (
                    <Check className="h-3.5 w-3.5" />
                  ) : partial ? (
                    <Minus className="h-3.5 w-3.5" />
                  ) : null}
                </span>
                <span className="min-w-0 flex-1 truncate">{p.title}</span>
                {isGroup ? (
                  <span className="shrink-0 text-xs text-muted tabular-nums">
                    {t("plex.playlistAdd.groupProgress", { in: n, size })}
                  </span>
                ) : (
                  <span className="shrink-0 text-xs text-muted">
                    {t("plex.playlistAdd.count", { count: p.item_count })}
                  </span>
                )}
              </button>
            );
          })
        )}
      </div>
    </Modal>
  );
}
