import { useParams, Link, useNavigate } from 'react-router-dom';
import { useBoard } from '../hooks/useBoard';
import { useCardMutations } from '../hooks/useCardMutations';
import { useListMutations } from '../hooks/useListMutations';
import { KanbanColumn } from '../components/kanban/KanbanColumn';
import {
  DndContext,
  DragEndEvent,
  DragOverlay,
  DragStartEvent,
  DragOverEvent,
  PointerSensor,
  useSensor,
  useSensors,
  closestCenter,
} from '@dnd-kit/core';
import { Card as CardType, BoardWithDetails } from '../types/kanban';
import { useState } from 'react';

export function BoardDetail() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { board, fetchBoard } = useBoard(parseInt(id || '0'));
  const { moveCard } = useCardMutations(parseInt(id || '0'), fetchBoard);
  const { createList } = useListMutations(parseInt(id || '0'), fetchBoard);

  const [activeCard, setActiveCard] = useState<CardType | null>(null);

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

  const handleDragStart = (event: DragStartEvent) => {
    const { active } = event;
    const cardId = parseInt(active.id as string);

    if (board) {
      const card = board.lists.flatMap((list) => list.cards).find((c) => c.id === cardId);

      if (card) {
        setActiveCard(card);
      }
    }
  };

  const handleDragOver = (event: DragOverEvent) => {
    const { active, over } = event;

    if (!over) return;

    const activeId = parseInt(active.id as string);
    const overId = parseInt(over.id as string);

    if (activeId === overId) return;

    // Find the active card and its current list
    if (!board) return;

    const activeList = board.lists.find((list) => list.cards.some((card) => card.id === activeId));

    // If we're hovering over a card in the same list, do nothing
    if (activeList) {
      const overCard = activeList.cards.find((card) => card.id === overId);
      if (overCard) return;
    }
  };

  const handleDragEnd = async (event: DragEndEvent) => {
    const { active, over } = event;
    setActiveCard(null);

    if (!over || !board) return;

    const activeId = parseInt(active.id as string);
    const overId = parseInt(over.id as string);

    if (activeId === overId) return;

    // Find the active card
    let activeCard: CardType | undefined;
    let activeList: (typeof board.lists)[0] | undefined;

    for (const list of board.lists) {
      const card = list.cards.find((c) => c.id === activeId);
      if (card) {
        activeCard = card;
        activeList = list;
        break;
      }
    }

    if (!activeCard || !activeList) return;

    // Check if we're dropping on a list or a card
    const overList = board.lists.find((list) => list.id === overId);

    if (overList) {
      // Dropping on a list - append to the end
      if (overList.id === activeList.id) return; // Same list, do nothing

      await moveCard(activeCard.id, activeList.id, overList.id, overList.cards.length);
      return;
    }

    // Dropping on a card - find which list it belongs to
    let overCard: CardType | undefined;
    let overListContainingCard: (typeof board.lists)[0] | undefined;

    for (const list of board.lists) {
      const card = list.cards.find((c) => c.id === overId);
      if (card) {
        overCard = card;
        overListContainingCard = list;
        break;
      }
    }

    if (!overCard || !overListContainingCard) return;

    // Calculate new position
    const overCardIndex = overListContainingCard.cards.findIndex((c) => c.id === overId);

    // If dropping on the same list and after the same card, do nothing
    if (
      overListContainingCard.id === activeList.id &&
      overCardIndex === activeList.cards.findIndex((c) => c.id === activeId) + 1
    ) {
      return;
    }

    await moveCard(activeCard.id, activeList.id, overListContainingCard.id, overCardIndex);
  };

  const handleCardClick = (card: CardType) => {
    navigate(`/boards/${id}/cards/${card.id}`);
  };

  const handleAddList = async () => {
    const listName = prompt('Enter list name:');
    if (listName && listName.trim()) {
      try {
        const newList = await createList(listName.trim(), board ? board.lists.length : 0);
      } catch (err) {
        // Error handled by hook
      }
    }
  };

  if (!board) {
    return <div className="text-white">Loading...</div>;
  }

  return (
    <div className="space-y-6">
      <div className="flex justify-between items-start">
        <div>
          <Link to="/boards" className="text-gray-400 hover:text-white transition-colors text-sm">
            ← Back to Boards
          </Link>
          <h1 className="text-3xl font-bold text-white mt-2">{board.name}</h1>
          {board.description && <p className="text-gray-400 mt-1">{board.description}</p>}
        </div>
        <div className="flex gap-2">
          <Link
            to={`/boards/${id}/edit`}
            className="bg-gray-700 hover:bg-gray-600 text-white font-medium py-2 px-4 rounded-lg transition-colors"
          >
            Edit Board
          </Link>
          <button
            onClick={handleAddList}
            className="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"
          >
            + Add List
          </button>
        </div>
      </div>

      <DndContext
        sensors={sensors}
        collisionDetection={closestCenter}
        onDragStart={handleDragStart}
        onDragOver={handleDragOver}
        onDragEnd={handleDragEnd}
      >
        <div className="flex gap-4 overflow-x-auto pb-4">
          {board.lists.map((list) => (
            <KanbanColumn
              key={list.id}
              list={list}
              cards={list.cards}
              onCardClick={handleCardClick}
            />
          ))}
        </div>

        <DragOverlay>
          {activeCard ? (
            <div className="bg-gray-700 rounded-lg p-4 cursor-grabbing border border-gray-600 shadow-lg opacity-80">
              <h3 className="text-white font-medium">{activeCard.name}</h3>
            </div>
          ) : null}
        </DragOverlay>
      </DndContext>
    </div>
  );
}
