"use client";

import { useCallback, useState } from "react";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { useTheme } from "next-themes";
import { MoreVertical, Trash2 } from "lucide-react";

import { cn } from "@/lib/utils";
import { Checkbox } from "@/components/ui/checkbox";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { getGroupColor } from "@/lib/colors";
import { useBoard } from "@/components/board/board-context";
import { NotesDialog } from "@/components/board/notes-dialog";
import { TodoCreatePopover } from "@/components/board/todo-create-popover";
import { TodoEditDialog } from "@/components/board/todo-edit-dialog";
import type { GroupDTO, TodoDTO } from "@/types/board";

export function GroupCard({ group }: { group: GroupDTO }) {
  const { toggleTodoDone, removeGroup } = useBoard();
  const { resolvedTheme } = useTheme();
  const [editingTodo, setEditingTodo] = useState<TodoDTO | null>(null);

  const {
    attributes,
    listeners,
    setNodeRef,
    setActivatorNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({
    id: group.id,
    data: { type: "group", categoryId: group.categoryId },
  });

  // dnd-kit's KeyboardSensor only treats Space/Enter as "pick up this card"
  // when the key event's target is this specific activator node -- but
  // that guard is skipped entirely if activatorNode.current is never set,
  // which left it preventDefault()-ing every Space/Enter keydown that
  // bubbled up through React's tree (not the DOM tree), including from
  // portaled Popover/Dialog content nested inside the card (the notes
  // editor, the "add to-do" popover). Wiring the same node as the
  // activator restores the target check.
  //
  // This must be memoized: a fresh function identity on every render makes
  // React detach+reattach the ref each time, which during a drag (many
  // re-renders as transform/isDragging change) resets dnd-kit's node
  // registration and broke drop detection entirely.
  const setCardRef = useCallback(
    (node: HTMLDivElement | null) => {
      setNodeRef(node);
      setActivatorNodeRef(node);
    },
    [setNodeRef, setActivatorNodeRef]
  );

  const color = getGroupColor(group.color);
  const borderColor = resolvedTheme === "dark" ? color.dark : color.light;

  return (
    <>
      <div
        ref={setCardRef}
        {...attributes}
        {...listeners}
        style={{
          transform: CSS.Transform.toString(transform),
          transition,
          borderColor,
        }}
        className={cn(
          "cursor-grab touch-none rounded-xl border-[3px] bg-card p-3 shadow-sm transition-shadow",
          "hover:-translate-y-0.5 hover:shadow-md active:cursor-grabbing",
          isDragging && "opacity-50 shadow-lg"
        )}
      >
        <div className="flex items-start justify-between gap-1">
          <h3 className="min-w-0 flex-1 truncate pt-1 text-sm font-semibold">{group.title}</h3>
          <div className="flex shrink-0 items-center">
            <NotesDialog group={group} />
            <DropdownMenu>
              <DropdownMenuTrigger
                render={
                  <button
                    className="flex size-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground"
                    aria-label={`More options for ${group.title}`}
                  >
                    <MoreVertical className="size-4" />
                  </button>
                }
              />
              <DropdownMenuContent align="end">
                <DropdownMenuItem
                  variant="destructive"
                  onClick={() => removeGroup(group.id, group.categoryId)}
                >
                  <Trash2 className="size-4" />
                  Delete group
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
          </div>
        </div>

        <ul className="mt-1 space-y-1">
          {group.todos.map((todo) => (
            <li key={todo.id} className="flex items-start gap-2 py-0.5">
              <Checkbox
                checked={todo.completed}
                onCheckedChange={(checked) =>
                  toggleTodoDone(todo.id, group.id, group.categoryId, checked === true)
                }
                className="mt-0.5"
                aria-label={`Mark "${todo.title}" ${todo.completed ? "incomplete" : "complete"}`}
              />
              <button
                type="button"
                onClick={() => setEditingTodo(todo)}
                className={cn(
                  "min-w-0 flex-1 truncate text-left text-sm hover:underline",
                  todo.completed && "text-muted-foreground line-through"
                )}
              >
                {todo.title}
              </button>
            </li>
          ))}
        </ul>

        <div className="mt-1">
          <TodoCreatePopover groupId={group.id} categoryId={group.categoryId} />
        </div>
      </div>

      {editingTodo && (
        <TodoEditDialog
          todo={editingTodo}
          groupId={group.id}
          categoryId={group.categoryId}
          open={!!editingTodo}
          onOpenChange={(open) => !open && setEditingTodo(null)}
        />
      )}
    </>
  );
}
