import { useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import type { LessonTreeNode } from '@flashcard/shared';
import { lessonsApi } from '../api/lessons.js';
import { useLessons } from '../stores/lessonsStore.js';
import { useAuth } from '../stores/authStore.js';
import {
  DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors,
  type DragEndEvent,
} from '@dnd-kit/core';
import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

function filterTree(nodes: LessonTreeNode[], q: string): LessonTreeNode[] {
  if (!q.trim()) return nodes;
  const term = q.trim().toLowerCase();
  function visit(n: LessonTreeNode): LessonTreeNode | null {
    const matches = n.name.toLowerCase().includes(term);
    const kids = n.children.map(visit).filter((x): x is LessonTreeNode => x !== null);
    if (matches || kids.length > 0) return { ...n, children: kids };
    return null;
  }
  return nodes.map(visit).filter((x): x is LessonTreeNode => x !== null);
}

function collectFlat(nodes: LessonTreeNode[]): LessonTreeNode[] {
  const out: LessonTreeNode[] = [];
  function walk(arr: LessonTreeNode[]) {
    for (const n of arr) { out.push(n); walk(n.children); }
  }
  walk(nodes);
  return out;
}

export function LessonTree({ nodes, filter = '' }: { nodes: LessonTreeNode[]; filter?: string }) {
  const filtered = useMemo(() => filterTree(nodes, filter), [nodes, filter]);
  const refresh = useLessons((s) => s.refresh);
  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
    useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
  );

  async function handleDragEnd(e: DragEndEvent) {
    const { active, over } = e;
    if (!over || active.id === over.id) return;
    const flat = collectFlat(filtered);
    const movedId = Number(active.id);
    const overId = Number(over.id);
    const moved = flat.find((x) => x.id === movedId);
    const overNode = flat.find((x) => x.id === overId);
    if (!moved || !overNode || moved.parentId !== overNode.parentId) return;
    const siblings = flat.filter((x) => x.parentId === moved.parentId);
    const newIdx = siblings.findIndex((x) => x.id === overId);
    if (newIdx < 0) return;
    try {
      await lessonsApi.move(movedId, { parentId: moved.parentId, position: newIdx });
      await refresh();
    } catch {/* ignore */}
  }

  return (
    <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
      <SortableContext items={filtered.map((n) => n.id)} strategy={verticalListSortingStrategy}>
        <ul className="space-y-1">
          {filtered.map((n) => <TreeRow key={n.id} n={n} depth={0} />)}
        </ul>
      </SortableContext>
    </DndContext>
  );
}

function TreeRow({ n, depth }: { n: LessonTreeNode; depth: number }) {
  const refresh = useLessons((s) => s.refresh);
  const currentUserId = useAuth((s) => s.user?.id);
  const isOwner = n.ownerId === currentUserId;
  const [addingTo, setAddingTo] = useState<number | null>(null);
  const [name, setName] = useState('');
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id: n.id, disabled: !isOwner,
  });
  const style = { transform: CSS.Transform.toString(transform), transition, opacity: isDragging ? 0.5 : 1 };

  async function addChild() {
    if (!name.trim()) return;
    await lessonsApi.create({ name: name.trim(), parentId: n.id });
    setName(''); setAddingTo(null); await refresh();
  }
  async function rename() {
    const next = prompt('Nieuwe naam', n.name);
    if (next && next.trim() && next !== n.name) {
      await lessonsApi.update(n.id, { name: next.trim() });
      await refresh();
    }
  }
  async function remove() {
    if (!confirm('Verwijder les en alle sublessen + kaarten?')) return;
    await lessonsApi.remove(n.id);
    await refresh();
  }

  const visibilityBadge =
    n.isCurated ? '⭐ Curated' : n.visibility === 'shared' ? '🌍 Gedeeld' : '🔒 Privé';

  return (
    <li style={{ paddingLeft: depth * 20 }} ref={setNodeRef}>
      <div
        style={style}
        className="group flex min-w-0 items-center gap-2 rounded-2xl px-3 py-2 transition hover:bg-brand-50/70 dark:hover:bg-slate-800/60"
      >
        {isOwner && (
          <span
            {...attributes} {...listeners}
            className="hidden shrink-0 cursor-grab text-slate-400 hover:text-slate-700 active:cursor-grabbing sm:inline"
            title="Sleep om te herordenen"
            aria-label="Drag handle"
          >⋮⋮</span>
        )}
        <span className={`h-2 w-2 shrink-0 rounded-full ${depth === 0 ? 'bg-brand-500' : 'bg-brand-300'}`} />
        <Link to={`/lessons/${n.id}`} className="min-w-0 flex-1 truncate font-medium text-slate-800 dark:text-slate-100">
          {n.name}
          <span className="ml-2 rounded-full bg-brand-100 px-2 py-0.5 text-xs font-semibold text-brand-700 dark:bg-brand-900/30 dark:text-brand-200">
            {n.cardCount}
          </span>
          <span className="ml-2 rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-semibold text-slate-600 dark:bg-slate-800 dark:text-slate-300">
            {visibilityBadge}
          </span>
          {!isOwner && (
            <span className="ml-1 rounded-full bg-amber-50 px-2 py-0.5 text-[10px] font-semibold text-amber-700 dark:bg-amber-900/30 dark:text-amber-200">
              📥 Geabonneerd
            </span>
          )}
        </Link>
        {isOwner && (
          <div className="hidden shrink-0 items-center gap-1 opacity-0 transition group-hover:opacity-100 sm:flex">
            <button className="rounded-lg px-2 py-1 text-xs font-medium text-brand-700 hover:bg-brand-100 dark:text-brand-200 dark:hover:bg-brand-900/40" onClick={() => setAddingTo(n.id)}>+ subles</button>
            <button className="rounded-lg px-2 py-1 text-xs font-medium text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800" onClick={rename}>rename</button>
            <button className="rounded-lg px-2 py-1 text-xs font-medium text-danger-600 hover:bg-danger-50 dark:hover:bg-danger-400/10" onClick={remove}>delete</button>
          </div>
        )}
      </div>
      {addingTo === n.id && (
        <div className="ml-6 mt-1 flex gap-2">
          <input
            autoFocus className="input-field flex-1" value={name}
            onChange={(e) => setName(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter') addChild(); if (e.key === 'Escape') { setAddingTo(null); setName(''); } }}
            placeholder="Naam van subles"
          />
          <button className="btn-primary px-3" onClick={addChild}>Toevoegen</button>
          <button className="btn-ghost px-3" onClick={() => { setAddingTo(null); setName(''); }}>Annuleren</button>
        </div>
      )}
      {n.children.length > 0 && (
        <SortableContext items={n.children.map((c) => c.id)} strategy={verticalListSortingStrategy}>
          <ul className="space-y-1">
            {n.children.map((c) => <TreeRow key={c.id} n={c} depth={depth + 1} />)}
          </ul>
        </SortableContext>
      )}
    </li>
  );
}
