"use client";

import { useState } from "react";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { useTheme } from "next-themes";
import {
  Archive,
  ClipboardList,
  GripVertical,
  MoreVertical,
  Pencil,
  Plus,
  Sparkles,
  StickyNote,
  Trash2,
} from "lucide-react";

import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { TodoCheckbox } from "@/components/board/todo-checkbox";
import { MouseFollowTooltip } from "@/components/board/mouse-follow-tooltip";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { getBrighterColor, getComplementaryColor, getGroupColor } from "@/lib/colors";
import { useBoard } from "@/components/board/board-context";
import { useBoardView } from "@/components/board/board-view-provider";
import { NotesDialog } from "@/components/board/notes-dialog";
import { TodoAiDialog } from "@/components/board/todo-ai-dialog";
import { TodoCreateDialog } from "@/components/board/todo-create-dialog";
import { TodoCreatePopover } from "@/components/board/todo-create-popover";
import { TodoEditDialog } from "@/components/board/todo-edit-dialog";
import { TodoProgressPie } from "@/components/board/todo-progress-pie";
import { EditGroupDialog } from "@/components/board/edit-group-dialog";
import { StatusUpdateDialog } from "@/components/board/status-update-dialog";
import { ConfirmDeleteDialog } from "@/components/confirm-delete-dialog";
import type { GroupDTO, TodoDTO } from "@/types/board";

// Compact's "+" -- sits inline on the last visible to-do row (its sibling
// text button is flex-1, so this shrink-0 trigger naturally lands at the
// row's right edge) instead of on a row of its own.
function AddTodoMenu({
  group,
  aiConfigured,
  onAddClick,
  onAiClick,
}: {
  group: GroupDTO;
  aiConfigured: boolean;
  onAddClick: () => void;
  onAiClick: () => void;
}) {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger
        render={
          <button
            className="flex size-6 shrink-0 items-center justify-center self-center rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground"
            aria-label={`Add a to-do to ${group.title}`}
          >
            <Plus className="size-3.5" />
          </button>
        }
      />
      <DropdownMenuContent align="end">
        <DropdownMenuItem onClick={onAddClick}>
          <Plus className="size-4" />
          Add to-do
        </DropdownMenuItem>
        {aiConfigured && (
          <DropdownMenuItem onClick={onAiClick}>
            <Sparkles className="size-4" />
            Add using AI
          </DropdownMenuItem>
        )}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

export function GroupCard({ group }: { group: GroupDTO }) {
  const { toggleTodoDone, removeGroup, archiveGroup, aiConfigured } = useBoard();
  const { view } = useBoardView();
  const compact = view === "compact";
  const { resolvedTheme } = useTheme();
  const [editingTodo, setEditingTodo] = useState<TodoDTO | null>(null);
  const [editOpen, setEditOpen] = useState(false);
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [todoAiOpen, setTodoAiOpen] = useState(false);
  const [todoCreateOpen, setTodoCreateOpen] = useState(false);
  const [statusUpdateOpen, setStatusUpdateOpen] = useState(false);

  const {
    attributes,
    listeners,
    setNodeRef,
    setActivatorNodeRef,
    transform,
    transition,
    isDragging,
    isOver,
  } = useSortable({
    id: group.id,
    data: { type: "group", categoryId: group.categoryId },
  });
  // Another card is being dragged and is currently hovering over this one
  // -- signal "it'll land near here" with a ring, distinct from this
  // card's own accent-colored border. (isDragging guards against this
  // card ever ringing itself while it's the one being moved.)
  const isDropTarget = isOver && !isDragging;

  const color = getGroupColor(group.color);
  const isDark = resolvedTheme === "dark";
  const borderColor = isDark ? color.dark : color.light;
  // A subdued tint of the same stroke color, blended into the theme's own
  // card surface -- not a fixed pastel, so it automatically stays correct
  // if the neutral card token ever changes, and needs no separate
  // light/dark background palette to hand-tune.
  const backgroundColor = isDark
    ? `color-mix(in srgb, ${color.dark} 18%, var(--card))`
    : `color-mix(in srgb, ${color.light} 12%, var(--card))`;
  // Opposing hue from the group's own color, for the progress pie below --
  // so it reads as a distinct accent rather than blending into the border.
  const pieAccentColor = getComplementaryColor(
    isDark ? color.dark : color.light,
    isDark ? "dark" : "light"
  );
  // Un-checked to-do text: a brighter tint of the group's own color rather
  // than the default (near-white in dark mode) foreground, so the group
  // title reads as the most prominent thing on the card.
  const todoTextColor = getBrighterColor(borderColor, isDark ? "dark" : "light");

  // Only offer archiving once there's actually something done -- a group
  // with no to-dos yet, or with any still open, isn't "finished" yet.
  const canArchive = group.todos.length > 0 && group.todos.every((t) => t.completed);
  const completedCount = group.todos.filter((t) => t.completed).length;
  // Compact only ever surfaces open work -- checked-off todos are dropped
  // from the list entirely rather than shown crossed-out.
  const visibleTodos = compact ? group.todos.filter((t) => !t.completed) : group.todos;

  return (
    <>
      <div
        ref={setNodeRef}
        style={{
          transform: CSS.Transform.toString(transform),
          transition,
          borderColor,
          backgroundColor,
        }}
        className={cn(
          "relative rounded-xl border-[3px] p-3 shadow-sm transition-shadow",
          "hover:-translate-y-0.5 hover:shadow-md",
          isDragging && "opacity-50 shadow-lg",
          isDropTarget && "ring-2 ring-primary ring-offset-2 ring-offset-background"
        )}
      >
        <div className="flex items-start justify-between gap-1">
          <div
            ref={setActivatorNodeRef}
            {...attributes}
            {...listeners}
            className="group flex min-w-0 flex-1 cursor-grab touch-none items-start gap-1 rounded-md outline-none active:cursor-grabbing focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
            aria-label={`Drag to move ${group.title}`}
          >
            <span className="mt-1 flex shrink-0 items-center justify-center text-muted-foreground/60 group-hover:text-muted-foreground">
              <GripVertical className="size-4" />
            </span>
            <h3 className="min-w-0 flex-1 truncate pt-1 text-sm font-semibold">{group.title}</h3>
          </div>
          <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 onClick={() => setEditOpen(true)}>
                  <Pencil className="size-4" />
                  Edit
                </DropdownMenuItem>
                {aiConfigured && (
                  <DropdownMenuItem onClick={() => setStatusUpdateOpen(true)}>
                    <ClipboardList className="size-4" />
                    Status Update
                  </DropdownMenuItem>
                )}
                <DropdownMenuSeparator />
                <DropdownMenuItem variant="destructive" onClick={() => setConfirmOpen(true)}>
                  <Trash2 className="size-4" />
                  Delete group
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
          </div>
        </div>

        <ul className="mt-1 space-y-1">
          {visibleTodos.map((todo, index) => {
            const todoButton = (
              <button
                type="button"
                onClick={() => setEditingTodo(todo)}
                style={todo.completed ? undefined : { color: todoTextColor }}
                className={cn(
                  "flex min-w-0 flex-1 items-center gap-1 text-left text-sm hover:underline",
                  todo.completed && "text-muted-foreground line-through"
                )}
              >
                <span className="min-w-0 truncate">{todo.title}</span>
                {todo.details && (
                  <StickyNote className="size-3 shrink-0 text-muted-foreground/70" />
                )}
              </button>
            );

            // In compact, the "+" rides along on the last visible row
            // instead of taking a row of its own -- one less line per
            // group. (A compact group always has at least one unchecked
            // to-do -- CategoryLane hides it otherwise -- so there's always
            // a last row to put it on.)
            const isLastRow = compact && index === visibleTodos.length - 1;

            return (
              <li key={todo.id} className="flex items-start gap-2 py-0.5">
                <TodoCheckbox
                  checked={todo.completed}
                  onCheckedChange={(checked) =>
                    toggleTodoDone(todo.id, group.id, group.categoryId, checked)
                  }
                  accentColor={borderColor}
                  isDark={isDark}
                  className="mt-0.5"
                  aria-label={`Mark "${todo.title}" ${todo.completed ? "incomplete" : "complete"}`}
                />
                {todo.details ? (
                  <MouseFollowTooltip content={todo.details}>{todoButton}</MouseFollowTooltip>
                ) : (
                  todoButton
                )}
                {isLastRow && (
                  <AddTodoMenu
                    group={group}
                    aiConfigured={aiConfigured}
                    onAddClick={() => setTodoCreateOpen(true)}
                    onAiClick={() => setTodoAiOpen(true)}
                  />
                )}
              </li>
            );
          })}
        </ul>

        {compact ? (
          // Defensive fallback -- shouldn't normally happen, since
          // CategoryLane already hides a compact group with zero visible
          // to-dos, but keeps the "+" reachable if that ever changes.
          visibleTodos.length === 0 && (
            <div className="mt-1 flex justify-end">
              <AddTodoMenu
                group={group}
                onAddClick={() => setTodoCreateOpen(true)}
                onAiClick={() => setTodoAiOpen(true)}
                aiConfigured={aiConfigured}
              />
            </div>
          )
        ) : (
          <>
            <div className="mt-1">
              <TodoCreatePopover groupId={group.id} categoryId={group.categoryId} />
            </div>

            {aiConfigured && (
              <Button
                variant="ghost"
                size="sm"
                className="w-full justify-start gap-2 text-muted-foreground"
                onClick={() => setTodoAiOpen(true)}
              >
                <Sparkles className="size-3.5" />
                Add using AI
              </Button>
            )}

            {canArchive && (
              <Button
                variant="ghost"
                size="sm"
                className="w-full justify-start gap-2 text-muted-foreground"
                onClick={() => archiveGroup(group.id, group.categoryId)}
              >
                <Archive className="size-3.5" />
                Archive
              </Button>
            )}

            <TodoProgressPie
              completed={completedCount}
              total={group.todos.length}
              accentColor={pieAccentColor}
            />
          </>
        )}
      </div>

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

      <EditGroupDialog group={group} open={editOpen} onOpenChange={setEditOpen} />

      <TodoAiDialog group={group} open={todoAiOpen} onOpenChange={setTodoAiOpen} />

      <TodoCreateDialog
        groupId={group.id}
        categoryId={group.categoryId}
        open={todoCreateOpen}
        onOpenChange={setTodoCreateOpen}
      />

      <StatusUpdateDialog group={group} open={statusUpdateOpen} onOpenChange={setStatusUpdateOpen} />

      <ConfirmDeleteDialog
        open={confirmOpen}
        onOpenChange={setConfirmOpen}
        title="Delete group?"
        description={`Delete "${group.title}" and all of its to-dos? This can't be undone.`}
        onConfirm={() => removeGroup(group.id, group.categoryId)}
      />
    </>
  );
}
