"use client";

import { useMemo, useState } from "react";
import {
  DndContext,
  type DragEndEvent,
  DragOverlay,
  type DragStartEvent,
  PointerSensor,
  useDroppable,
  useSensor,
  useSensors,
  closestCorners,
} from "@dnd-kit/core";
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
import { Loader2, Plus, Trash2 } from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { deleteTaskAction, moveTaskAction } from "@/lib/appwrite/task-actions";
import { cn } from "@/lib/utils";

import { TaskCard } from "./task-card";
import { TaskFormSheet } from "./task-form-sheet";
import {
  COLUMNS,
  type Customer,
  type TaskRow,
  type TaskStatus,
  type TeamMember,
} from "./types";
import { useTransition } from "react";

type Props = {
  tasks: TaskRow[];
  customers: Customer[];
  teamMembers: TeamMember[];
};

function Column({
  status,
  title,
  tasks,
  onAdd,
  onEdit,
  onDelete,
}: {
  status: TaskStatus;
  title: string;
  tasks: TaskRow[];
  onAdd: (status: TaskStatus) => void;
  onEdit: (task: TaskRow) => void;
  onDelete: (task: TaskRow) => void;
}) {
  const { setNodeRef, isOver } = useDroppableColumn(status);

  return (
    <div className="bg-muted/40 flex flex-col rounded-lg border">
      <div className="flex items-center justify-between border-b px-3 py-2.5">
        <div className="flex items-center gap-2">
          <h2 className="text-sm font-semibold">{title}</h2>
          <span className="text-muted-foreground bg-muted rounded-full px-1.5 py-0.5 text-xs">
            {tasks.length}
          </span>
        </div>
        <Button
          variant="ghost"
          size="icon"
          className="size-7"
          onClick={() => onAdd(status)}
          aria-label="Yeni görev"
        >
          <Plus className="size-3.5" />
        </Button>
      </div>

      <div
        ref={setNodeRef}
        className={cn(
          "flex flex-1 flex-col gap-2 p-2 transition-colors",
          isOver && "bg-primary/5",
        )}
      >
        <SortableContext
          items={tasks.map((t) => t.id)}
          strategy={verticalListSortingStrategy}
        >
          {tasks.map((task) => (
            <TaskCard key={task.id} task={task} onEdit={onEdit} onDelete={onDelete} />
          ))}
        </SortableContext>
        {tasks.length === 0 && (
          <p className="text-muted-foreground py-8 text-center text-xs">Boş</p>
        )}
      </div>
    </div>
  );
}

function useDroppableColumn(status: TaskStatus) {
  return useDroppable({
    id: `col-${status}`,
    data: { type: "column", status },
  });
}

export function TasksBoard({ tasks: initialTasks, customers, teamMembers }: Props) {
  const [tasks, setTasks] = useState<TaskRow[]>(initialTasks);
  const [activeId, setActiveId] = useState<string | null>(null);
  const [formOpen, setFormOpen] = useState(false);
  const [formStatus, setFormStatus] = useState<TaskStatus>("todo");
  const [editing, setEditing] = useState<TaskRow | null>(null);
  const [deleting, setDeleting] = useState<TaskRow | null>(null);
  const [busy, startTransition] = useTransition();

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

  const grouped = useMemo(() => {
    const map: Record<TaskStatus, TaskRow[]> = {
      backlog: [],
      todo: [],
      in_progress: [],
      done: [],
    };
    for (const t of tasks) {
      map[t.status].push(t);
    }
    return map;
  }, [tasks]);

  const activeTask = useMemo(
    () => tasks.find((t) => t.id === activeId) ?? null,
    [tasks, activeId],
  );

  const onDragStart = (e: DragStartEvent) => {
    setActiveId(String(e.active.id));
  };

  const onDragEnd = (e: DragEndEvent) => {
    const { active, over } = e;
    setActiveId(null);
    if (!over || active.id === over.id) return;

    const activeData = active.data.current as { type?: string; status?: TaskStatus } | undefined;
    const overData = over.data.current as { type?: string; status?: TaskStatus } | undefined;
    if (activeData?.type !== "task") return;

    let targetStatus: TaskStatus | undefined;
    if (overData?.type === "column" && overData.status) {
      targetStatus = overData.status;
    } else if (overData?.type === "task" && overData.status) {
      targetStatus = overData.status;
    }
    if (!targetStatus) return;

    const sourceTask = tasks.find((t) => t.id === active.id);
    if (!sourceTask) return;

    // Compute new order: place after the over item, or end of column
    const targetTasks = tasks.filter(
      (t) => t.status === targetStatus && t.id !== active.id,
    );
    let newOrder: number;
    if (overData?.type === "task") {
      const overIndex = targetTasks.findIndex((t) => t.id === over.id);
      if (overIndex === -1) {
        newOrder = (targetTasks[targetTasks.length - 1]?.order ?? 0) + 1000;
      } else {
        const before = targetTasks[overIndex - 1]?.order ?? 0;
        const at = targetTasks[overIndex].order;
        newOrder = (before + at) / 2;
      }
    } else {
      newOrder = (targetTasks[targetTasks.length - 1]?.order ?? 0) + 1000;
    }

    // Optimistic update
    setTasks((prev) =>
      prev.map((t) => (t.id === sourceTask.id ? { ...t, status: targetStatus!, order: newOrder } : t)),
    );

    startTransition(async () => {
      const result = await moveTaskAction(sourceTask.id, targetStatus!, newOrder);
      if (!result.ok) {
        // Rollback
        setTasks((prev) =>
          prev.map((t) =>
            t.id === sourceTask.id ? { ...t, status: sourceTask.status, order: sourceTask.order } : t,
          ),
        );
        toast.error(result.error ?? "Görev taşınamadı.");
      }
    });
  };

  // Keep local state in sync when server data changes (e.g., after revalidate)
  useMemo(() => setTasks(initialTasks), [initialTasks]);

  const handleAdd = (status: TaskStatus) => {
    setEditing(null);
    setFormStatus(status);
    setFormOpen(true);
  };

  const handleDelete = () => {
    if (!deleting) return;
    startTransition(async () => {
      const fd = new FormData();
      fd.set("id", deleting.id);
      const result = await deleteTaskAction(fd);
      if (result.ok) {
        toast.success("Görev silindi.");
        setDeleting(null);
      } else {
        toast.error(result.error ?? "Silme başarısız.");
      }
    });
  };

  return (
    <>
      <div className="flex justify-end">
        <Button onClick={() => handleAdd("todo")}>
          <Plus className="size-4" />
          Yeni görev
        </Button>
      </div>

      <DndContext
        sensors={sensors}
        collisionDetection={closestCorners}
        onDragStart={onDragStart}
        onDragEnd={onDragEnd}
      >
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
          {COLUMNS.map((col) => (
            <Column
              key={col.key}
              status={col.key}
              title={col.title}
              tasks={grouped[col.key]}
              onAdd={handleAdd}
              onEdit={(t) => {
                setEditing(t);
                setFormOpen(true);
              }}
              onDelete={(t) => setDeleting(t)}
            />
          ))}
        </div>

        <DragOverlay>
          {activeTask && (
            <TaskCard
              task={activeTask}
              onEdit={() => {}}
              onDelete={() => {}}
              isOverlay
            />
          )}
        </DragOverlay>
      </DndContext>

      <TaskFormSheet
        open={formOpen}
        onOpenChange={(v) => {
          setFormOpen(v);
          if (!v) setEditing(null);
        }}
        task={editing}
        defaultStatus={formStatus}
        customers={customers}
        teamMembers={teamMembers}
      />

      <Dialog open={Boolean(deleting)} onOpenChange={(v) => !v && setDeleting(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Görevi sil</DialogTitle>
            <DialogDescription>
              <strong>{deleting?.title}</strong> kalıcı olarak silinecek.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDeleting(null)} disabled={busy}>
              Vazgeç
            </Button>
            <Button variant="destructive" onClick={handleDelete} disabled={busy}>
              {busy ? <Loader2 className="size-4 animate-spin" /> : <Trash2 className="size-4" />}
              Sil
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
