import { Draggable, Droppable } from "@hello-pangea/dnd";
import { Add, AddCircle, CloseCircle } from "iconsax-react";
import { useMemo, useRef, useState, type FC } from "react";
import { useTranslation } from "react-i18next";
import { toast } from '../../../components/Toast';
import ModalConfrim from "../../../components/ModalConfrim";
import { ErrorType } from "../../../helpers/types";
import { useCreateTask, useGetTasksByTaskPhase } from "../task/hooks/useTaskData";
import type { TaskItemType } from "../task/types/TaskTypes";
import { mapTaskItemToTask } from "../task/utils/mapTaskItemToTask";
import { useDeleteTaskPhase, useUpdateTaskPhase } from "../task-phase/hooks/useTaskPhaseData";
import type { Column as ColumnType, Task as TaskType } from "../types";
import ColumnMenu from "./ColumnMenu";
import Task from "./Task";

type Props = {
  column: ColumnType;
  projectId: string;
  draggedColumnId: string | null;
  onColumnDragStart: (columnId: string) => void;
  onColumnDragEnd: () => void;
  onColumnDrop: (overColumnId: string) => void;
  onTaskClick?: (task: TaskType) => void;
  onColumnDeleted?: (columnId: string) => void;
  onColumnTitleUpdated?: (columnId: string, title: string) => void;
};

const Column: FC<Props> = ({
  column,
  projectId,
  draggedColumnId,
  onColumnDragStart,
  onColumnDragEnd,
  onColumnDrop,
  onTaskClick,
  onColumnDeleted,
  onColumnTitleUpdated,
}) => {
  const { t } = useTranslation("global");
  const deleteTaskPhase = useDeleteTaskPhase();
  const updateTaskPhase = useUpdateTaskPhase();
  const createTask = useCreateTask();
  const {
    data: tasksData,
    isPending: isTasksPending,
    isFetchingNextPage,
    fetchNextPage,
    hasNextPage,
  } = useGetTasksByTaskPhase(column.id);

  const tasks = useMemo(() => {
    const items = tasksData?.pages.flatMap((page) => page.data?.items ?? []) ?? [];

    return [...items]
      .sort((a, b) => (a.order ?? a.priority ?? 0) - (b.order ?? b.priority ?? 0))
      .map((task, index) => mapTaskItemToTask(task as TaskItemType, column.id, index));
  }, [tasksData?.pages, column.id]);

  const [isAdding, setIsAdding] = useState(false);
  const [title, setTitle] = useState("");
  const [isEditingTitle, setIsEditingTitle] = useState(false);
  const [editTitle, setEditTitle] = useState(column.title);
  const [isDeleteConfirmOpen, setIsDeleteConfirmOpen] = useState(false);
  const [isColumnDragOver, setIsColumnDragOver] = useState(false);
  const columnRef = useRef<HTMLDivElement>(null);
  const dragImageRef = useRef<HTMLElement | null>(null);
  const isCancellingTitleEdit = useRef(false);
  const isDraggingColumn = draggedColumnId === column.id;

  const handleTasksScroll = (event: React.UIEvent<HTMLDivElement>) => {
    const target = event.currentTarget;
    const isNearBottom = target.scrollHeight - target.scrollTop - target.clientHeight < 80;

    if (isNearBottom && hasNextPage && !isFetchingNextPage) {
      fetchNextPage();
    }
  };

  const handleColumnDragStart = (e: React.DragEvent) => {
    const columnEl = columnRef.current;
    if (columnEl) {
      const clone = columnEl.cloneNode(true) as HTMLElement;
      clone.style.position = "fixed";
      clone.style.top = "-10000px";
      clone.style.left = "-10000px";
      clone.style.width = `${columnEl.offsetWidth}px`;
      clone.style.opacity = "0.95";
      clone.style.boxShadow = "0 8px 24px rgba(0, 0, 0, 0.15)";
      clone.style.pointerEvents = "none";
      clone.style.zIndex = "9999";
      document.body.appendChild(clone);
      dragImageRef.current = clone;

      const rect = columnEl.getBoundingClientRect();
      e.dataTransfer.setDragImage(clone, e.clientX - rect.left, e.clientY - rect.top);
      e.dataTransfer.effectAllowed = "move";
    }

    onColumnDragStart(column.id);
  };

  const handleColumnDragEnd = () => {
    if (dragImageRef.current) {
      document.body.removeChild(dragImageRef.current);
      dragImageRef.current = null;
    }
    onColumnDragEnd();
  };

  const handleColumnDragOver = (e: React.DragEvent) => {
    if (!draggedColumnId || draggedColumnId === column.id) return;
    e.preventDefault();
    e.dataTransfer.dropEffect = "move";
    setIsColumnDragOver(true);
  };

  const handleColumnDragLeave = (e: React.DragEvent) => {
    if (!draggedColumnId) return;
    if (!e.currentTarget.contains(e.relatedTarget as Node)) {
      setIsColumnDragOver(false);
    }
  };

  const handleColumnDrop = (e: React.DragEvent) => {
    if (!draggedColumnId || draggedColumnId === column.id) return;
    e.preventDefault();
    e.stopPropagation();
    setIsColumnDragOver(false);
    onColumnDrop(column.id);
  };

  const resetTaskForm = () => {
    setTitle("");
    setIsAdding(false);
  };

  const handleCreateTask = () => {
    const trimmedTitle = title.trim();
    if (!trimmedTitle || !projectId) return;

    createTask.mutate(
      {
        title: trimmedTitle,
        taskPhaseId: column.id,
        order: tasks.length,
        projectId,
      },
      {
        onSuccess: () => {
          toast(t("success"), 'success');
          resetTaskForm();
        },
        onError: (error: ErrorType) => {
          toast(error.response?.data?.error.message[0], 'error');
        },
      },
    );
  };

  const handleDeleteColumn = () => {
    deleteTaskPhase.mutate(
      { id: column.id, projectId },
      {
        onSuccess: () => {
          onColumnDeleted?.(column.id);
          setIsDeleteConfirmOpen(false);
          toast(t("taskmanager.column_deleted"), 'success');
        },
        onError: (error: ErrorType) => {
          toast(error.response?.data?.error.message[0], 'error');
        },
      },
    );
  };

  const startEditingTitle = () => {
    isCancellingTitleEdit.current = false;
    setEditTitle(column.title);
    setIsEditingTitle(true);
  };

  const cancelEditingTitle = () => {
    isCancellingTitleEdit.current = true;
    setEditTitle(column.title);
    setIsEditingTitle(false);
  };

  const handleSaveTitle = () => {
    if (isCancellingTitleEdit.current) {
      isCancellingTitleEdit.current = false;
      return;
    }

    const trimmedTitle = editTitle.trim();
    if (!trimmedTitle || trimmedTitle === column.title) {
      setIsEditingTitle(false);
      setEditTitle(column.title);
      return;
    }

    const previousTitle = column.title;
    onColumnTitleUpdated?.(column.id, trimmedTitle);
    setIsEditingTitle(false);

    updateTaskPhase.mutate(
      { id: column.id, params: { name: trimmedTitle }, projectId },
      {
        onSuccess: () => {
          toast(t("taskmanager.column_updated"), 'success');
        },
        onError: (error: ErrorType) => {
          onColumnTitleUpdated?.(column.id, previousTitle);
          setEditTitle(previousTitle);
          toast(error.response?.data?.error.message[0], 'error');
        },
      },
    );
  };

  return (
    <div
      ref={columnRef}
      className={`bg-[#F0F3F7] rounded-xl p-3 sm:p-4 xl:p-6 w-[272px] sm:w-[288px] xl:w-[310px] shrink-0 flex flex-col h-full min-h-0 transition-colors ${
        isColumnDragOver ? "ring-2 ring-black/30" : ""
      } ${isDraggingColumn ? "opacity-50" : ""}`}
      onDragOver={handleColumnDragOver}
      onDragLeave={handleColumnDragLeave}
      onDrop={handleColumnDrop}
    >
      <div className="flex justify-between items-center shrink-0 gap-2">
        {isEditingTitle ? (
          <input
            type="text"
            value={editTitle}
            onChange={(e) => setEditTitle(e.target.value)}
            onBlur={handleSaveTitle}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                e.preventDefault();
                handleSaveTitle();
              }
              if (e.key === "Escape") {
                e.preventDefault();
                cancelEditingTitle();
              }
            }}
            disabled={updateTaskPhase.isPending}
            className="flex-1 min-w-0 font-bold text-sm bg-white rounded-lg px-2 py-1 outline-none"
            autoFocus
          />
        ) : (
          <div
            draggable
            onDragStart={handleColumnDragStart}
            onDragEnd={handleColumnDragEnd}
            onDoubleClick={startEditingTitle}
            className="flex-1 min-w-0 font-bold text-sm truncate cursor-grab active:cursor-grabbing"
          >
            {column.title}
          </div>
        )}
        <ColumnMenu onEdit={startEditingTitle} onDelete={() => setIsDeleteConfirmOpen(true)} />
      </div>

      <ModalConfrim
        isOpen={isDeleteConfirmOpen}
        close={() => setIsDeleteConfirmOpen(false)}
        onConfrim={handleDeleteColumn}
        isLoading={deleteTaskPhase.isPending}
        label={t("taskmanager.delete_column_confirm")}
      />

      <Droppable droppableId={column.id} type="TASK" isDropDisabled={!!draggedColumnId}>
        {(provided, snapshot) => (
          <div
            ref={provided.innerRef}
            {...provided.droppableProps}
            onScroll={handleTasksScroll}
            className={`mt-3 sm:mt-4 xl:mt-5 flex-1 min-h-[80px] overflow-y-auto overscroll-y-contain rounded-lg transition-colors ${
              snapshot.isDraggingOver ? "bg-primary/5 ring-2 ring-primary/30" : ""
            }`}
          >
            {isTasksPending
              ? null
              : tasks.map((task, index) => (
                  <Draggable
                    key={task.id}
                    draggableId={task.id}
                    index={index}
                    isDragDisabled={!!draggedColumnId}
                  >
                    {(dragProvided, dragSnapshot) => (
                      <div
                        ref={dragProvided.innerRef}
                        {...dragProvided.draggableProps}
                        {...dragProvided.dragHandleProps}
                        className="mb-3 sm:mb-4"
                        style={dragProvided.draggableProps.style}
                      >
                        <Task
                          task={task}
                          isDragging={dragSnapshot.isDragging}
                          onClick={onTaskClick}
                        />
                      </div>
                    )}
                  </Draggable>
                ))}
            {provided.placeholder}
            {isFetchingNextPage ? (
              <div className="text-center text-description text-xs py-2">{t("loading")}</div>
            ) : null}
          </div>
        )}
      </Droppable>

      {isAdding ? (
        <div className="mt-3 sm:mt-4 xl:mt-5 shrink-0 flex flex-col gap-3">
          <input
            type="text"
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === "Enter") handleCreateTask();
            }}
            placeholder={t("taskmanager.task_title")}
            className="w-full bg-white rounded-lg px-3 py-2.5 text-sm outline-none"
            autoFocus
          />
          <div className="flex items-center gap-2">
            <button
              type="button"
              onClick={handleCreateTask}
              disabled={!title.trim() || createTask.isPending}
              className="flex items-center gap-2 bg-black text-white text-[13px] rounded-full px-4 py-2 cursor-pointer disabled:opacity-50"
            >
              <span>{t("taskmanager.add_task")}</span>
              <Add size={18} color="white" />
            </button>
            <button
              type="button"
              onClick={resetTaskForm}
              className="cursor-pointer"
              aria-label={t("cancel")}
            >
              <CloseCircle size={22} color="#888888" variant="Bold" />
            </button>
          </div>
        </div>
      ) : (
        <button
          type="button"
          onClick={() => setIsAdding(true)}
          className="mt-3 sm:mt-4 xl:mt-5 flex gap-2 items-center shrink-0 cursor-pointer"
        >
          <AddCircle size={18} color="#888888" />
          <span className="text-description text-[13px] mt-0.5">{t("taskmanager.add_new_task")}</span>
        </button>
      )}
    </div>
  );
};

export default Column;
