"use client";

import { useState, useMemo } from "react";
import {
  DndContext,
  closestCorners,
  MouseSensor,
  TouchSensor,
  useSensor,
  useSensors,
  type DragEndEvent,
  type DragStartEvent,
  DragOverlay,
} from "@dnd-kit/core";
import {
  SortableContext,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import {
  Circle,
  CheckCircle2,
  Calendar,
  GripVertical,
  Plus,
  MoreHorizontal,
  Pencil,
  Trash2,
  X,
  Check,
  User2,
  Flag,
} from "lucide-react";
import { cn, formatRelativeDate, isTaskDeadlineOverdue } from "@/lib/utils";
import type { TaskWithRelations } from "@/hooks/use-tasks";
import type { TaskBucket } from "@/types";

const PRIORITY_DOT: Record<string, string> = {
  urgent: "#ef4444",
  high: "#f97316",
  medium: "#eab308",
  low: "#3b82f6",
};

// ─── Sortable Task Card ─────────────────────────────────────
function SortableTaskCard({
  task,
  onToggle,
  onClick,
  editable,
  currentUserId,
}: {
  task: TaskWithRelations;
  onToggle: () => void;
  onClick: () => void;
  editable: boolean;
  currentUserId?: string | null;
}) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({
    id: task.id,
    data: { type: "task", bucketId: task.bucket_id },
    disabled: !editable,
  });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.4 : 1,
  };

  return (
    <div ref={setNodeRef} style={style} className="group/card">
      <TaskKanbanCard
        task={task}
        onToggle={onToggle}
        onClick={onClick}
        editable={editable}
        currentUserId={currentUserId}
        dragHandleProps={{ ...attributes, ...listeners }}
      />
    </div>
  );
}

function TaskKanbanCard({
  task,
  onToggle,
  onClick,
  editable = true,
  dragHandleProps,
  currentUserId,
}: {
  task: TaskWithRelations;
  onToggle: () => void;
  onClick: () => void;
  editable?: boolean;
  dragHandleProps?: Record<string, unknown>;
  currentUserId?: string | null;
}) {
  const isDone = task.status === "done";
  const isOverdue = task.deadline && !isDone && isTaskDeadlineOverdue(task.deadline);
  const prioColor = PRIORITY_DOT[task.priority];
  const needsMyLead =
    (!!currentUserId &&
      task.reviewer_id === currentUserId &&
      task.review_status === "pending_review") ||
    (!!currentUserId &&
      task.assignee_id === currentUserId &&
      task.review_status === "changes_requested");

  return (
    <div
      className={cn(
        "rounded-xl border p-3 transition-all duration-150 cursor-pointer shadow-sm hover:shadow-md",
        needsMyLead
          ? "border-amber-500/40 bg-amber-500/[0.05] hover:border-amber-500/60"
          : "border-border/50 bg-card hover:border-border"
      )}
      onClick={onClick}
    >
      <div className="flex items-start gap-2">
        {/* Drag handle */}
        <button
          className="shrink-0 mt-0.5 opacity-0 group-hover/card:opacity-100 transition-opacity cursor-grab active:cursor-grabbing p-0.5"
          {...dragHandleProps}
          onClick={(e) => e.stopPropagation()}
          disabled={!editable}
        >
          <GripVertical className="h-3.5 w-3.5 text-muted-foreground/50" />
        </button>

        {/* Checkbox */}
        <button
          onClick={(e) => {
            e.stopPropagation();
            onToggle();
          }}
          disabled={!editable}
          className="shrink-0 mt-0.5 cursor-pointer text-muted-foreground hover:text-foreground transition-colors"
        >
          {isDone ? (
            <CheckCircle2 className="h-4 w-4 text-emerald-500" />
          ) : (
            <Circle className="h-4 w-4" />
          )}
        </button>

        {/* Content */}
        <div className="flex-1 min-w-0">
          <span
            className={cn(
              "text-[13px] font-medium leading-snug block",
              isDone && "line-through text-muted-foreground/60"
            )}
          >
            {task.title}
          </span>

          {/* Meta */}
          <div className="flex items-center gap-2 mt-1.5 flex-wrap">
            {prioColor && task.priority !== "none" && (
              <span
                className="w-1.5 h-1.5 rounded-full shrink-0"
                style={{ backgroundColor: prioColor }}
              />
            )}
            {task.deadline && (
              <span
                className={cn(
                  "inline-flex items-center gap-1 text-[10px]",
                  isOverdue ? "text-red-500" : "text-muted-foreground"
                )}
              >
                <Calendar className="h-2.5 w-2.5" />
                {formatRelativeDate(task.deadline)}
              </span>
            )}
            {task.assignee && (
              <span className="inline-flex items-center gap-1 text-[10px] text-muted-foreground">
                <User2 className="h-2.5 w-2.5" />
                {task.assignee.full_name || task.assignee.email}
              </span>
            )}
            {needsMyLead && (
              <span className="inline-flex items-center gap-1 rounded-full bg-amber-500/15 px-1.5 py-0 text-[9px] font-semibold text-amber-700 dark:text-amber-400">
                <Flag className="h-2.5 w-2.5" />
                Take the lead
              </span>
            )}
            {task.tags.slice(0, 2).map((tag) => (
              <span
                key={tag.id}
                className="rounded-full px-1.5 py-0 text-[9px] font-medium"
                style={{ backgroundColor: tag.color + "18", color: tag.color }}
              >
                {tag.name}
              </span>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Kanban Column ──────────────────────────────────────────
function KanbanColumn({
  bucket,
  tasks,
  onToggle,
  onClick,
  onRenameBucket,
  onDeleteBucket,
  canDelete,
  editable = true,
  currentUserId,
  autoRename,
}: {
  bucket: TaskBucket;
  tasks: TaskWithRelations[];
  onToggle: (id: string, status: string) => void;
  onClick: (task: TaskWithRelations) => void;
  onRenameBucket: (id: string, name: string) => void;
  onDeleteBucket: (id: string) => void;
  canDelete: boolean;
  editable?: boolean;
  currentUserId?: string | null;
  autoRename?: boolean;
}) {
  const [menuOpen, setMenuOpen] = useState(false);
  const [renaming, setRenaming] = useState(!!autoRename);
  const [renameValue, setRenameValue] = useState(bucket.name);

  const { setNodeRef } = useSortable({
    id: bucket.id,
    data: { type: "column", bucketId: bucket.id },
    disabled: true,
  });

  function handleRename() {
    if (renameValue.trim()) {
      onRenameBucket(bucket.id, renameValue.trim());
    }
    setRenaming(false);
    setMenuOpen(false);
  }

  return (
    <div ref={setNodeRef} className="flex flex-col w-[300px] shrink-0">
      {/* Column header */}
      <div className="flex items-center justify-between mb-3 px-1">
        <div className="flex items-center gap-2.5">
          <div
            className="w-2.5 h-2.5 rounded-full"
            style={{ backgroundColor: bucket.color }}
          />
          {renaming ? (
            <div className="flex items-center gap-1">
              <input
                value={renameValue}
                onChange={(e) => setRenameValue(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === "Enter") handleRename();
                  if (e.key === "Escape") { setRenaming(false); setRenameValue(bucket.name); }
                }}
                className="text-sm font-semibold bg-transparent border-b border-border focus:border-foreground outline-none w-32"
                autoFocus
              />
              <button onClick={handleRename} className="p-0.5 hover:bg-accent rounded">
                <Check className="h-3.5 w-3.5 text-emerald-500" />
              </button>
              <button onClick={() => { setRenaming(false); setRenameValue(bucket.name); }} className="p-0.5 hover:bg-accent rounded">
                <X className="h-3.5 w-3.5 text-muted-foreground" />
              </button>
            </div>
          ) : (
            <h3 className="text-sm font-semibold tracking-tight">{bucket.name}</h3>
          )}
          <span className="text-[10px] font-medium text-muted-foreground bg-muted rounded-full px-2 py-0.5 tabular-nums">
            {tasks.length}
          </span>
        </div>

        {/* Bucket menu */}
        {!renaming && (
          <div className="relative">
            <button
              onClick={() => setMenuOpen(!menuOpen)}
              className="p-1 rounded-md hover:bg-accent transition-colors text-muted-foreground hover:text-foreground"
            >
              <MoreHorizontal className="h-4 w-4" />
            </button>
            {menuOpen && (
              <>
                <div className="fixed inset-0 z-40" onClick={() => setMenuOpen(false)} />
                <div className="absolute right-0 top-8 z-50 w-40 rounded-xl border border-border bg-popover shadow-lg py-1">
                  <button
                    className="flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-accent transition-colors text-left"
                    onClick={() => { setRenaming(true); setMenuOpen(false); }}
                  >
                    <Pencil className="h-3.5 w-3.5" />
                    Umbenennen
                  </button>
                  {canDelete && (
                    <button
                      className="flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-accent transition-colors text-left text-red-500"
                      onClick={() => { onDeleteBucket(bucket.id); setMenuOpen(false); }}
                    >
                      <Trash2 className="h-3.5 w-3.5" />
                      Löschen
                    </button>
                  )}
                </div>
              </>
            )}
          </div>
        )}
      </div>

      {/* Cards */}
      <div className="rounded-xl bg-muted/30 border border-border/30 p-2 space-y-2 min-h-[160px]">
        <SortableContext
          items={tasks.map((t) => t.id)}
          strategy={verticalListSortingStrategy}
        >
          {tasks.map((task) => (
            <SortableTaskCard
              key={task.id}
              task={task}
              onToggle={() => onToggle(task.id, task.status)}
              onClick={() => onClick(task)}
              editable={editable}
              currentUserId={currentUserId}
            />
          ))}
        </SortableContext>

        {tasks.length === 0 && (
          <div className="flex items-center justify-center h-20 text-[11px] text-muted-foreground">
            Aufgaben hierher ziehen
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Main Kanban Board ──────────────────────────────────────
interface TaskKanbanProps {
  tasks: TaskWithRelations[];
  buckets: TaskBucket[];
  onToggle: (id: string, status: string) => void;
  onClick: (task: TaskWithRelations) => void;
  onMoveTask: (id: string, bucketId: string) => void;
  onCreateBucket: () => Promise<TaskBucket>;
  onRenameBucket: (id: string, name: string) => void;
  onDeleteBucket: (id: string) => void;
  editable?: boolean;
  currentUserId?: string | null;
}

export function TaskKanban({
  tasks,
  buckets,
  onToggle,
  onClick,
  onMoveTask,
  onCreateBucket,
  onRenameBucket,
  onDeleteBucket,
  editable = true,
  currentUserId,
}: TaskKanbanProps) {
  const [activeId, setActiveId] = useState<string | null>(null);
  const [freshBucketId, setFreshBucketId] = useState<string | null>(null);

  const sensors = useSensors(
    useSensor(MouseSensor, { activationConstraint: { distance: 5 } }),
    useSensor(TouchSensor, { activationConstraint: { delay: 200, tolerance: 8 } })
  );

  // Group tasks by bucket — tasks whose bucket_id doesn't match any current
  // bucket (or has none) fall back into the first bucket so nothing is lost.
  const tasksByBucket = useMemo(() => {
    const map = new Map<string, TaskWithRelations[]>();
    for (const bucket of buckets) {
      map.set(bucket.id, []);
    }
    for (const task of tasks) {
      const list = task.bucket_id ? map.get(task.bucket_id) : undefined;
      if (list) {
        list.push(task);
      } else {
        const first = buckets[0] ? map.get(buckets[0].id) : undefined;
        if (first) first.push(task);
      }
    }
    return map;
  }, [tasks, buckets]);

  const activeTask = activeId ? tasks.find((t) => t.id === activeId) : null;

  function handleDragStart(event: DragStartEvent) {
    if (!editable) return;
    setActiveId(event.active.id as string);
  }

  function handleDragOver() {
    // Not needed for simple column drop
  }

  function handleDragEnd(event: DragEndEvent) {
    if (!editable) return;
    setActiveId(null);
    const { active, over } = event;
    if (!over) return;

    const taskId = active.id as string;
    const task = tasks.find((t) => t.id === taskId);
    if (!task) return;

    // Find which bucket the task was dropped into
    const overData = over.data.current;
    let targetBucketId: string | null = null;

    if (overData?.type === "column") {
      targetBucketId = overData.bucketId as string;
    } else if (overData?.type === "task") {
      // Dropped onto another task — find that task's bucket
      const overTask = tasks.find((t) => t.id === over.id);
      if (overTask) targetBucketId = overTask.bucket_id;
    }

    if (targetBucketId && targetBucketId !== task.bucket_id) {
      onMoveTask(taskId, targetBucketId);
    }
  }

  async function handleAddBucket() {
    if (!editable) return;
    const bucket = await onCreateBucket();
    setFreshBucketId(bucket.id);
  }

  return (
    <div className="space-y-4">
      <DndContext
        sensors={sensors}
        collisionDetection={closestCorners}
        onDragStart={handleDragStart}
        onDragOver={handleDragOver}
        onDragEnd={handleDragEnd}
      >
        <div className="flex items-start gap-4 overflow-x-auto pb-4 -mx-2 px-2">
          {buckets.map((bucket) => (
            <KanbanColumn
              key={bucket.id}
              bucket={bucket}
              tasks={tasksByBucket.get(bucket.id) || []}
              onToggle={onToggle}
              onClick={onClick}
              onRenameBucket={onRenameBucket}
              onDeleteBucket={onDeleteBucket}
              canDelete={buckets.length > 1}
              editable={editable}
              currentUserId={currentUserId}
              autoRename={bucket.id === freshBucketId}
            />
          ))}

          {/* Add bucket button */}
          {editable && (
            <div className="min-w-[200px] shrink-0">
              <button
                onClick={handleAddBucket}
                className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground px-3 py-2 rounded-xl border border-dashed border-border/50 hover:border-border transition-all w-full justify-center mt-8"
              >
                <Plus className="h-4 w-4" />
                Bucket hinzufügen
              </button>
            </div>
          )}
        </div>

        {/* Drag overlay */}
        <DragOverlay>
          {activeTask && (
            <div className="w-[300px]">
              <TaskKanbanCard
                task={activeTask}
                onToggle={() => {}}
                onClick={() => {}}
                editable={editable}
                currentUserId={currentUserId}
              />
            </div>
          )}
        </DragOverlay>
      </DndContext>
    </div>
  );
}
