import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  DndContext,
  PointerSensor,
  closestCenter,
  useSensor,
  useSensors,
  type DragEndEvent,
} from "@dnd-kit/core";
import {
  SortableContext,
  arrayMove,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import {
  Check,
  GripVertical,
  ListPlus,
  Pencil,
  Play,
  Plus,
  Trash2,
  X,
} from "lucide-react";
import { api, type Playlist, type Video } from "../lib/api";
import { formatDuration } from "../lib/format";
import PlayerModal from "./PlayerModal";

function Row({
  video,
  index,
  onPlay,
  onRemove,
}: {
  video: Video;
  index: number;
  onPlay: () => void;
  onRemove: () => void;
}) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } =
    useSortable({ id: video.id });
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.6 : 1,
  };
  return (
    <div
      ref={setNodeRef}
      style={style}
      className="flex items-center gap-2.5 p-2 rounded-lg border border-border bg-card"
    >
      <button
        {...attributes}
        {...listeners}
        className="text-muted hover:text-fg cursor-grab active:cursor-grabbing"
        aria-label="reorder"
      >
        <GripVertical className="w-4 h-4" />
      </button>
      <span className="text-xs text-muted w-4 text-center tabular-nums">{index + 1}</span>
      <button
        onClick={onPlay}
        className="relative w-[62px] h-[35px] rounded overflow-hidden bg-surface shrink-0 group"
      >
        {video.thumbnail_url && (
          <img src={video.thumbnail_url} alt="" className="w-full h-full object-cover" />
        )}
        <span className="absolute inset-0 grid place-items-center bg-black/40 opacity-0 group-hover:opacity-100 transition">
          <Play className="w-4 h-4 text-white fill-current" />
        </span>
      </button>
      <button onClick={onPlay} className="min-w-0 flex-1 text-left">
        <div className="text-[13px] text-fg truncate">{video.title}</div>
        <div className="text-[11px] text-muted truncate">{video.channel_title}</div>
      </button>
      {video.duration_seconds != null && (
        <span className="text-[11px] text-muted tabular-nums">
          {formatDuration(video.duration_seconds)}
        </span>
      )}
      <button
        onClick={onRemove}
        title="remove"
        className="text-muted hover:text-fg p-1"
        aria-label="remove from playlist"
      >
        <X className="w-4 h-4" />
      </button>
    </div>
  );
}

export default function Playlists() {
  const { t } = useTranslation();
  const qc = useQueryClient();
  const [selectedId, setSelectedId] = useState<number | null>(null);
  const [newName, setNewName] = useState("");
  const [renaming, setRenaming] = useState(false);
  const [renameValue, setRenameValue] = useState("");
  const [items, setItems] = useState<Video[]>([]);
  const [active, setActive] = useState<{ video: Video; startAt: number | null } | null>(null);

  const listQuery = useQuery({ queryKey: ["playlists"], queryFn: () => api.playlists() });
  const playlists = listQuery.data ?? [];

  // Default the selection to the first playlist once the list loads.
  useEffect(() => {
    if (selectedId == null && playlists.length) setSelectedId(playlists[0].id);
  }, [playlists, selectedId]);

  const detailQuery = useQuery({
    queryKey: ["playlist", selectedId],
    queryFn: () => api.playlist(selectedId as number),
    enabled: selectedId != null,
  });
  const detail = detailQuery.data;

  useEffect(() => {
    if (detail) setItems(detail.items);
  }, [detail]);

  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 4 } })
  );

  const createMut = useMutation({
    mutationFn: (name: string) => api.createPlaylist(name),
    onSuccess: (pl: Playlist) => {
      setNewName("");
      qc.invalidateQueries({ queryKey: ["playlists"] });
      setSelectedId(pl.id);
    },
  });

  function refreshAll() {
    qc.invalidateQueries({ queryKey: ["playlists"] });
    qc.invalidateQueries({ queryKey: ["playlist", selectedId] });
  }

  async function onDragEnd(e: DragEndEvent) {
    const { active: a, over } = e;
    if (!over || a.id === over.id || selectedId == null) return;
    const oldIndex = items.findIndex((v) => v.id === a.id);
    const newIndex = items.findIndex((v) => v.id === over.id);
    if (oldIndex < 0 || newIndex < 0) return;
    const next = arrayMove(items, oldIndex, newIndex);
    setItems(next);
    await api.reorderPlaylist(selectedId, next.map((v) => v.id));
    qc.invalidateQueries({ queryKey: ["playlist", selectedId] });
  }

  async function removeItem(videoId: string) {
    if (selectedId == null) return;
    setItems((cur) => cur.filter((v) => v.id !== videoId));
    await api.removeFromPlaylist(selectedId, videoId);
    refreshAll();
  }

  async function saveRename() {
    if (selectedId == null) return;
    const name = renameValue.trim();
    setRenaming(false);
    if (name && name !== detail?.name) {
      await api.renamePlaylist(selectedId, name);
      refreshAll();
    }
  }

  async function deletePlaylist() {
    if (selectedId == null || !detail) return;
    if (!window.confirm(t("playlists.confirmDelete", { name: detail.name }))) return;
    await api.deletePlaylist(selectedId);
    setSelectedId(null);
    qc.invalidateQueries({ queryKey: ["playlists"] });
  }

  function playerState(id: string, status: string) {
    api.setState(id, status).then(() => {
      qc.invalidateQueries({ queryKey: ["playlist", selectedId] });
      qc.invalidateQueries({ queryKey: ["feed"] });
    });
  }

  return (
    <div className="flex h-full min-h-0">
      <aside className="w-64 shrink-0 border-r border-border bg-surface/40 overflow-y-auto p-3">
        <div className="text-sm font-semibold mb-2">{t("playlists.title")}</div>
        {playlists.length === 0 && !listQuery.isLoading && (
          <div className="text-xs text-muted px-1 py-2">{t("playlists.noneYet")}</div>
        )}
        <div className="space-y-1">
          {playlists.map((pl) => (
            <button
              key={pl.id}
              onClick={() => setSelectedId(pl.id)}
              className={`w-full flex items-center gap-2.5 p-2 rounded-lg border transition text-left ${
                pl.id === selectedId
                  ? "bg-accent/15 border-accent"
                  : "border-transparent hover:bg-card/60"
              }`}
            >
              <div className="w-[34px] h-[34px] rounded-md bg-card overflow-hidden shrink-0">
                {pl.cover_thumbnail && (
                  <img src={pl.cover_thumbnail} alt="" className="w-full h-full object-cover" />
                )}
              </div>
              <div className="min-w-0">
                <div className="text-[13px] text-fg truncate">{pl.name}</div>
                <div className="text-[11px] text-muted">
                  {t("playlists.itemCount", { count: pl.item_count })}
                </div>
              </div>
            </button>
          ))}
        </div>
        <form
          onSubmit={(e) => {
            e.preventDefault();
            if (newName.trim()) createMut.mutate(newName.trim());
          }}
          className="flex items-center gap-1.5 mt-3 pt-3 border-t border-border"
        >
          <Plus className="w-4 h-4 text-muted shrink-0" />
          <input
            value={newName}
            onChange={(e) => setNewName(e.target.value)}
            placeholder={t("playlists.newPlaylist")}
            className="flex-1 min-w-0 bg-card border border-border rounded-md px-2 py-1 text-xs outline-none focus:border-accent"
          />
        </form>
      </aside>

      <main className="flex-1 min-w-0 overflow-y-auto p-4">
        {!detail ? (
          <div className="text-muted text-sm p-4">
            {selectedId == null ? t("playlists.pickOne") : t("playlists.loading")}
          </div>
        ) : (
          <>
            <div className="flex gap-3 items-start mb-4">
              <div className="w-24 h-[54px] rounded-lg bg-card overflow-hidden shrink-0">
                {items[0]?.thumbnail_url && (
                  <img
                    src={items[0].thumbnail_url}
                    alt=""
                    className="w-full h-full object-cover"
                  />
                )}
              </div>
              <div className="min-w-0 flex-1">
                {renaming ? (
                  <input
                    autoFocus
                    value={renameValue}
                    onChange={(e) => setRenameValue(e.target.value)}
                    onBlur={saveRename}
                    onKeyDown={(e) => {
                      if (e.key === "Enter") saveRename();
                      if (e.key === "Escape") setRenaming(false);
                    }}
                    className="text-lg font-semibold bg-card border border-border rounded-md px-2 py-0.5 outline-none focus:border-accent"
                  />
                ) : (
                  <div className="flex items-center gap-2">
                    <h2 className="text-lg font-semibold truncate">{detail.name}</h2>
                    <button
                      onClick={() => {
                        setRenameValue(detail.name);
                        setRenaming(true);
                      }}
                      title={t("playlists.rename")}
                      className="text-muted hover:text-fg"
                    >
                      <Pencil className="w-3.5 h-3.5" />
                    </button>
                  </div>
                )}
                <div className="text-xs text-muted mt-0.5">
                  {t("playlists.itemCount", { count: items.length })}
                </div>
                <div className="flex gap-2 mt-3 flex-wrap">
                  <button
                    onClick={() => items[0] && setActive({ video: items[0], startAt: null })}
                    disabled={!items.length}
                    className="inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-1.5 rounded-lg bg-accent text-accent-fg disabled:opacity-40 hover:opacity-90 transition"
                  >
                    <Play className="w-3.5 h-3.5 fill-current" /> {t("playlists.playAll")}
                  </button>
                  <button
                    onClick={deletePlaylist}
                    className="inline-flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-lg border border-border text-muted hover:text-fg hover:border-accent transition"
                  >
                    <Trash2 className="w-3.5 h-3.5" /> {t("playlists.delete")}
                  </button>
                </div>
              </div>
            </div>

            {items.length === 0 ? (
              <div className="text-sm text-muted grid place-items-center text-center py-12">
                <div>
                  <ListPlus className="w-6 h-6 mx-auto mb-2 opacity-60" />
                  {t("playlists.empty")}
                </div>
              </div>
            ) : (
              <DndContext
                sensors={sensors}
                collisionDetection={closestCenter}
                onDragEnd={onDragEnd}
              >
                <SortableContext
                  items={items.map((v) => v.id)}
                  strategy={verticalListSortingStrategy}
                >
                  <div className="space-y-1.5 max-w-3xl">
                    {items.map((v, i) => (
                      <Row
                        key={v.id}
                        video={v}
                        index={i}
                        onPlay={() => setActive({ video: v, startAt: null })}
                        onRemove={() => removeItem(v.id)}
                      />
                    ))}
                  </div>
                </SortableContext>
              </DndContext>
            )}
          </>
        )}
      </main>

      {active && (
        <PlayerModal
          video={active.video}
          startAt={active.startAt}
          onClose={() => setActive(null)}
          onState={playerState}
        />
      )}
    </div>
  );
}
