import React, { useState, useRef, useEffect, useCallback } from "react";
import { Plus } from "lucide-react";
import { motion } from "framer-motion";
import { staggerContainer } from "@/lib/motion";
import {
  DndContext,
  DragOverlay,
  closestCorners,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  type DragStartEvent,
  type DragOverEvent,
  type DragEndEvent,
} from "@dnd-kit/core";
import {
  SortableContext,
  horizontalListSortingStrategy,
} from "@dnd-kit/sortable";
import { Button } from "@/components/ui/button";
import { useBoardStore } from "@/stores/board-store";
import { KanbanColumn } from "@/components/board/KanbanColumn";
import {
  CardOverlay,
  ColumnOverlay,
} from "@/components/board/DragOverlayContent";
import { CardDetailModal } from "@/components/card-detail/CardDetailModal";
import type { Board } from "@/types/board";

function findColumnByCardId(board: Board, cardId: string) {
  return board.columns.find((col) => col.cardIds.includes(cardId));
}

function getBoardBackground(board: Board): React.CSSProperties {
  const bg = board.settings.background;
  if (bg === "dots") {
    return {
      backgroundImage: `radial-gradient(circle, currentColor 1px, transparent 1px)`,
      backgroundSize: "20px 20px",
      color: "oklch(50% 0 0 / 5%)",
    };
  }
  if (bg === "grid") {
    return {
      backgroundImage: `linear-gradient(currentColor 1px, transparent 1px), linear-gradient(90deg, currentColor 1px, transparent 1px)`,
      backgroundSize: "24px 24px",
      color: "oklch(50% 0 0 / 5%)",
    };
  }
  if (bg === "gradient") {
    return {
      background: `linear-gradient(135deg, ${board.color}08, ${board.color}03, transparent)`,
    };
  }
  return {};
}

export function BoardView() {
  const board = useBoardStore((s) => s.board);
  const addColumn = useBoardStore((s) => s.addColumn);
  const moveCard = useBoardStore((s) => s.moveCard);
  const moveColumn = useBoardStore((s) => s.moveColumn);

  const [selectedCardId, setSelectedCardId] = useState<string | null>(null);
  const [addingColumn, setAddingColumn] = useState(false);
  const [newColumnTitle, setNewColumnTitle] = useState("");
  const inputRef = useRef<HTMLInputElement>(null);

  // Listen for custom event to open card detail from command palette
  useEffect(() => {
    function handleOpenCard(e: Event) {
      const detail = (e as CustomEvent<{ cardId: string }>).detail;
      if (detail?.cardId) {
        setSelectedCardId(detail.cardId);
      }
    }
    document.addEventListener("open-card-detail", handleOpenCard);
    return () => {
      document.removeEventListener("open-card-detail", handleOpenCard);
    };
  }, []);

  // Drag state
  const [activeId, setActiveId] = useState<string | null>(null);
  const [activeType, setActiveType] = useState<"card" | "column" | null>(null);

  // Sensors: PointerSensor with distance of 5px prevents accidental drags on click
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: { distance: 5 },
    }),
    useSensor(KeyboardSensor)
  );

  useEffect(() => {
    if (addingColumn && inputRef.current) {
      inputRef.current.focus();
    }
  }, [addingColumn]);

  function handleAddColumn() {
    const trimmed = newColumnTitle.trim();
    if (trimmed) {
      addColumn(trimmed);
      setNewColumnTitle("");
      inputRef.current?.focus();
    }
  }

  function handleKeyDown(e: React.KeyboardEvent) {
    if (e.key === "Enter") {
      handleAddColumn();
    } else if (e.key === "Escape") {
      setAddingColumn(false);
      setNewColumnTitle("");
    }
  }

  // --- Drag handlers ---

  const handleDragStart = useCallback((event: DragStartEvent) => {
    const { active } = event;
    const type = active.data.current?.type as "card" | "column" | undefined;
    setActiveId(active.id as string);
    setActiveType(type ?? null);
  }, []);

  const handleDragOver = useCallback(
    (event: DragOverEvent) => {
      const { active, over } = event;
      if (!over || !board) return;

      const activeType = active.data.current?.type;
      if (activeType !== "card") return; // Only handle card cross-column moves here

      const activeCardId = active.id as string;
      const overId = over.id as string;

      // Determine the source column
      const activeColumn = findColumnByCardId(board, activeCardId);
      if (!activeColumn) return;

      // Determine the target column
      let overColumn: ReturnType<typeof findColumnByCardId>;
      let overIndex: number;

      // Check if we're hovering over a card
      const overType = over.data.current?.type;
      if (overType === "card") {
        overColumn = findColumnByCardId(board, overId);
        if (!overColumn) return;
        overIndex = overColumn.cardIds.indexOf(overId);
      } else if (overType === "column") {
        // Hovering over the droppable area of a column
        const columnId = over.data.current?.columnId as string | undefined;
        if (columnId) {
          overColumn = board.columns.find((c) => c.id === columnId);
        } else {
          overColumn = board.columns.find((c) => c.id === overId);
        }
        if (!overColumn) return;
        overIndex = overColumn.cardIds.length; // Append to end
      } else {
        return;
      }

      // Only move if we're going to a different column or different position
      if (activeColumn.id === overColumn.id) return;

      moveCard(activeCardId, activeColumn.id, overColumn.id, overIndex);
    },
    [board, moveCard]
  );

  const handleDragEnd = useCallback(
    (event: DragEndEvent) => {
      const { active, over } = event;

      if (!over || !board) {
        setActiveId(null);
        setActiveType(null);
        return;
      }

      const type = active.data.current?.type;

      if (type === "column") {
        // Column reordering
        const activeColumnId = active.id as string;
        const overColumnId = over.id as string;

        if (activeColumnId !== overColumnId) {
          const fromIndex = board.columns.findIndex(
            (c) => c.id === activeColumnId
          );
          const toIndex = board.columns.findIndex(
            (c) => c.id === overColumnId
          );
          if (fromIndex !== -1 && toIndex !== -1) {
            moveColumn(fromIndex, toIndex);
          }
        }
      } else if (type === "card") {
        // Card reordering within same column (cross-column already handled in onDragOver)
        const activeCardId = active.id as string;
        const overId = over.id as string;

        const activeColumn = findColumnByCardId(board, activeCardId);
        if (!activeColumn) {
          setActiveId(null);
          setActiveType(null);
          return;
        }

        const overType = over.data.current?.type;

        if (overType === "card") {
          const overColumn = findColumnByCardId(board, overId);
          if (!overColumn) {
            setActiveId(null);
            setActiveType(null);
            return;
          }

          if (activeColumn.id === overColumn.id) {
            // Within same column, reorder
            const oldIndex = activeColumn.cardIds.indexOf(activeCardId);
            const newIndex = activeColumn.cardIds.indexOf(overId);
            if (oldIndex !== newIndex) {
              moveCard(activeCardId, activeColumn.id, activeColumn.id, newIndex);
            }
          }
        } else if (overType === "column") {
          // Dropped on an empty column droppable
          const columnId = over.data.current?.columnId as string | undefined;
          const targetColumnId = columnId ?? (over.id as string);
          const targetColumn = board.columns.find(
            (c) => c.id === targetColumnId
          );

          if (targetColumn && activeColumn.id !== targetColumn.id) {
            moveCard(
              activeCardId,
              activeColumn.id,
              targetColumn.id,
              targetColumn.cardIds.length
            );
          }
        }
      }

      setActiveId(null);
      setActiveType(null);
    },
    [board, moveCard, moveColumn]
  );

  const [announcement, setAnnouncement] = useState("");

  const handleDragEndWithAnnouncement = useCallback(
    (event: DragEndEvent) => {
      handleDragEnd(event);
      const { active, over } = event;
      if (over && board) {
        const type = active.data.current?.type;
        if (type === "card") {
          const card = board.cards[active.id as string];
          const targetCol = over.data.current?.type === "column"
            ? board.columns.find((c) => c.id === (over.data.current?.columnId ?? over.id))
            : findColumnByCardId(board, over.id as string);
          if (card && targetCol) {
            setAnnouncement(`Moved card "${card.title}" to ${targetCol.title}`);
          }
        } else if (type === "column") {
          const col = board.columns.find((c) => c.id === (active.id as string));
          if (col) {
            setAnnouncement(`Reordered column "${col.title}"`);
          }
        }
      }
    },
    [handleDragEnd, board]
  );

  if (!board) {
    return (
      <div className="flex h-full items-center justify-center text-pylon-text-secondary">
        <span className="font-mono text-sm">Loading board...</span>
      </div>
    );
  }

  // Get the active item for the drag overlay
  const activeCard =
    activeType === "card" && activeId ? board.cards[activeId] : null;
  const activeColumn =
    activeType === "column" && activeId
      ? board.columns.find((c) => c.id === activeId)
      : null;

  const columnIds = board.columns.map((c) => c.id);

  return (
    <>
    {/* Visually hidden live region for drag-and-drop announcements */}
    <div
      aria-live="polite"
      aria-atomic="true"
      className="sr-only"
    >
      {announcement}
    </div>
    <DndContext
      sensors={sensors}
      collisionDetection={closestCorners}
      onDragStart={handleDragStart}
      onDragOver={handleDragOver}
      onDragEnd={handleDragEndWithAnnouncement}
    >
      <SortableContext
        items={columnIds}
        strategy={horizontalListSortingStrategy}
      >
        <motion.div
          className="flex h-full overflow-x-auto"
          style={{ gap: `calc(1.5rem * var(--density-factor))`, padding: `calc(1.5rem * var(--density-factor))`, ...getBoardBackground(board) }}
          variants={staggerContainer(0.06)}
          initial="hidden"
          animate="visible"
        >
          {board.columns.map((column) => (
            <KanbanColumn
              key={column.id}
              column={column}
              onCardClick={setSelectedCardId}
            />
          ))}

          {/* Add column button / inline input */}
          <div className="shrink-0">
            {addingColumn ? (
              <div className="flex w-[280px] flex-col gap-2 rounded-lg bg-pylon-column p-3">
                <input
                  ref={inputRef}
                  value={newColumnTitle}
                  onChange={(e) => setNewColumnTitle(e.target.value)}
                  onKeyDown={handleKeyDown}
                  onBlur={() => {
                    if (!newColumnTitle.trim()) {
                      setAddingColumn(false);
                    }
                  }}
                  placeholder="Column title..."
                  className="h-8 rounded-md bg-pylon-surface px-3 text-sm text-pylon-text outline-none placeholder:text-pylon-text-secondary focus:ring-1 focus:ring-pylon-accent"
                />
                <div className="flex gap-2">
                  <Button size="sm" onClick={handleAddColumn}>
                    Add
                  </Button>
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => {
                      setAddingColumn(false);
                      setNewColumnTitle("");
                    }}
                    className="text-pylon-text-secondary"
                  >
                    Cancel
                  </Button>
                </div>
              </div>
            ) : (
              <Button
                variant="ghost"
                size="sm"
                onClick={() => setAddingColumn(true)}
                className="h-10 w-[280px] justify-start border border-dashed border-pylon-text-secondary/30 text-pylon-text-secondary hover:border-pylon-text-secondary/60 hover:text-pylon-text"
              >
                <Plus className="size-4" />
                Add column
              </Button>
            )}
          </div>
        </motion.div>
      </SortableContext>

      {/* Drag overlay - renders a styled copy of the dragged item */}
      <DragOverlay>
        {activeCard ? (
          <CardOverlay card={activeCard} boardLabels={board.labels} />
        ) : activeColumn ? (
          <ColumnOverlay column={activeColumn} />
        ) : null}
      </DragOverlay>
    </DndContext>

    <CardDetailModal
      cardId={selectedCardId}
      onClose={() => setSelectedCardId(null)}
    />
    </>
  );
}
