"use client";

import { useState, useEffect, useCallback } from "react";
import type { ReactElement } from "react";
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
import type {
  DropResult,
  DroppableProvided,
  DraggableProvided,
  DraggableStateSnapshot,
} from "@hello-pangea/dnd";

import { MosaicSpinner } from "@/components/ui/MosaicSpinner";
import { fetchTasks, updateTask } from "@/lib/api/tasks";
import { useWorkspaceId } from "@/lib/hooks";
import type { Task } from "@mosaic/shared";
import { TaskStatus, TaskPriority } from "@mosaic/shared";

/* ---------------------------------------------------------------------------
   Column configuration
   --------------------------------------------------------------------------- */

interface ColumnConfig {
  status: TaskStatus;
  label: string;
  accent: string;
}

const COLUMNS: ColumnConfig[] = [
  { status: TaskStatus.NOT_STARTED, label: "To Do", accent: "var(--ms-blue-400)" },
  { status: TaskStatus.IN_PROGRESS, label: "In Progress", accent: "var(--ms-amber-400)" },
  { status: TaskStatus.PAUSED, label: "Paused", accent: "var(--ms-purple-400)" },
  { status: TaskStatus.COMPLETED, label: "Done", accent: "var(--ms-teal-400)" },
  { status: TaskStatus.ARCHIVED, label: "Archived", accent: "var(--muted)" },
];

/* ---------------------------------------------------------------------------
   Priority badge helper
   --------------------------------------------------------------------------- */

interface PriorityStyle {
  label: string;
  bg: string;
  color: string;
}

function getPriorityStyle(priority: TaskPriority): PriorityStyle {
  switch (priority) {
    case TaskPriority.HIGH:
      return { label: "High", bg: "rgba(229,72,77,0.15)", color: "var(--danger)" };
    case TaskPriority.MEDIUM:
      return { label: "Medium", bg: "rgba(245,158,11,0.15)", color: "var(--warn)" };
    case TaskPriority.LOW:
      return { label: "Low", bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
    default:
      return { label: String(priority), bg: "rgba(143,157,183,0.15)", color: "var(--muted)" };
  }
}

/* ---------------------------------------------------------------------------
   Task Card
   --------------------------------------------------------------------------- */

interface TaskCardProps {
  task: Task;
  provided: DraggableProvided;
  snapshot: DraggableStateSnapshot;
  columnAccent: string;
}

function TaskCard({ task, provided, snapshot, columnAccent }: TaskCardProps): ReactElement {
  const [hovered, setHovered] = useState(false);
  const priorityStyle = getPriorityStyle(task.priority);

  return (
    <div
      ref={provided.innerRef}
      {...provided.draggableProps}
      {...provided.dragHandleProps}
      onMouseEnter={() => {
        setHovered(true);
      }}
      onMouseLeave={() => {
        setHovered(false);
      }}
      style={{
        background: "var(--surface)",
        border: `1px solid ${hovered || snapshot.isDragging ? columnAccent : "var(--border)"}`,
        borderRadius: "var(--r)",
        padding: 12,
        marginBottom: 8,
        cursor: "grab",
        transition: "border-color 0.15s, box-shadow 0.15s",
        boxShadow: snapshot.isDragging ? "var(--shadow-lg)" : "none",
        ...provided.draggableProps.style,
      }}
    >
      {/* Title */}
      <div
        style={{
          fontWeight: 600,
          color: "var(--text)",
          fontSize: "0.875rem",
          marginBottom: 6,
          overflow: "hidden",
          textOverflow: "ellipsis",
          whiteSpace: "nowrap",
        }}
      >
        {task.title}
      </div>

      {/* Priority badge */}
      <span
        style={{
          display: "inline-block",
          padding: "1px 8px",
          borderRadius: "var(--r-sm)",
          background: priorityStyle.bg,
          color: priorityStyle.color,
          fontSize: "0.7rem",
          fontWeight: 500,
          marginBottom: 6,
        }}
      >
        {priorityStyle.label}
      </span>

      {/* Description */}
      {task.description && (
        <p
          style={{
            color: "var(--muted)",
            fontSize: "0.8rem",
            margin: 0,
            overflow: "hidden",
            textOverflow: "ellipsis",
            display: "-webkit-box",
            WebkitLineClamp: 2,
            WebkitBoxOrient: "vertical",
            lineHeight: 1.4,
          }}
        >
          {task.description}
        </p>
      )}
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Kanban Column
   --------------------------------------------------------------------------- */

interface KanbanColumnProps {
  config: ColumnConfig;
  tasks: Task[];
}

function KanbanColumn({ config, tasks }: KanbanColumnProps): ReactElement {
  return (
    <div
      style={{
        minWidth: 280,
        maxWidth: 340,
        flex: "1 0 280px",
        display: "flex",
        flexDirection: "column",
        background: "var(--bg-mid)",
        borderRadius: "var(--r-lg)",
        overflow: "hidden",
      }}
    >
      {/* Column header */}
      <div
        style={{
          borderTop: `3px solid ${config.accent}`,
          padding: "12px 16px",
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
        }}
      >
        <span
          style={{
            fontWeight: 600,
            fontSize: "0.85rem",
            color: "var(--text)",
          }}
        >
          {config.label}
        </span>
        <span
          style={{
            display: "inline-flex",
            alignItems: "center",
            justifyContent: "center",
            minWidth: 22,
            height: 22,
            padding: "0 6px",
            borderRadius: "var(--r)",
            background: `color-mix(in srgb, ${config.accent} 15%, transparent)`,
            color: config.accent,
            fontSize: "0.75rem",
            fontWeight: 600,
            fontFamily: "var(--mono)",
          }}
        >
          {tasks.length}
        </span>
      </div>

      {/* Droppable area */}
      <Droppable droppableId={config.status}>
        {(provided: DroppableProvided) => (
          <div
            ref={provided.innerRef}
            {...provided.droppableProps}
            style={{
              padding: "8px 12px 12px",
              flex: 1,
              minHeight: 80,
              overflowY: "auto",
            }}
          >
            {tasks.map((task, index) => (
              <Draggable key={task.id} draggableId={task.id} index={index}>
                {(dragProvided: DraggableProvided, dragSnapshot: DraggableStateSnapshot) => (
                  <TaskCard
                    task={task}
                    provided={dragProvided}
                    snapshot={dragSnapshot}
                    columnAccent={config.accent}
                  />
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </div>
  );
}

/* ---------------------------------------------------------------------------
   Kanban Board Page
   --------------------------------------------------------------------------- */

export default function KanbanPage(): ReactElement {
  const workspaceId = useWorkspaceId();
  const [tasks, setTasks] = useState<Task[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  /* --- data fetching --- */

  const loadTasks = useCallback(async (wsId: string | null): Promise<void> => {
    try {
      setIsLoading(true);
      setError(null);
      const filters = wsId !== null ? { workspaceId: wsId } : {};
      const data = await fetchTasks(filters);
      setTasks(data);
    } catch (err: unknown) {
      console.error("[Kanban] Failed to fetch tasks:", err);
      setError(
        err instanceof Error
          ? err.message
          : "Something went wrong loading tasks. You could try again when ready."
      );
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!workspaceId) {
      setIsLoading(false);
      return;
    }

    let cancelled = false;

    async function load(): Promise<void> {
      try {
        setIsLoading(true);
        setError(null);
        const filters = workspaceId !== null ? { workspaceId } : {};
        const data = await fetchTasks(filters);
        if (!cancelled) {
          setTasks(data);
        }
      } catch (err: unknown) {
        console.error("[Kanban] Failed to fetch tasks:", err);
        if (!cancelled) {
          setError(
            err instanceof Error
              ? err.message
              : "Something went wrong loading tasks. You could try again when ready."
          );
        }
      } finally {
        if (!cancelled) {
          setIsLoading(false);
        }
      }
    }

    void load();

    return (): void => {
      cancelled = true;
    };
  }, [workspaceId]);

  /* --- group tasks by status --- */

  function groupByStatus(allTasks: Task[]): Record<TaskStatus, Task[]> {
    const grouped: Record<TaskStatus, Task[]> = {
      [TaskStatus.NOT_STARTED]: [],
      [TaskStatus.IN_PROGRESS]: [],
      [TaskStatus.PAUSED]: [],
      [TaskStatus.COMPLETED]: [],
      [TaskStatus.ARCHIVED]: [],
    };

    for (const task of allTasks) {
      grouped[task.status].push(task);
    }

    return grouped;
  }

  const grouped = groupByStatus(tasks);

  /* --- drag-and-drop handler --- */

  const handleDragEnd = useCallback(
    (result: DropResult) => {
      const { source, destination, draggableId } = result;

      // Dropped outside a droppable area
      if (!destination) return;

      // Dropped in same position
      if (source.droppableId === destination.droppableId && source.index === destination.index) {
        return;
      }

      const newStatus = destination.droppableId as TaskStatus;
      const taskId = draggableId;

      // Optimistic update: move card in local state
      setTasks((prev) => prev.map((t) => (t.id === taskId ? { ...t, status: newStatus } : t)));

      // Persist to API
      const wsId = workspaceId ?? undefined;
      updateTask(taskId, { status: newStatus }, wsId).catch((err: unknown) => {
        console.error("[Kanban] Failed to update task status:", err);
        // Revert on failure by re-fetching
        void loadTasks(workspaceId);
      });
    },
    [workspaceId, loadTasks]
  );

  /* --- retry handler --- */

  function handleRetry(): void {
    void loadTasks(workspaceId);
  }

  /* --- render --- */

  return (
    <main style={{ padding: "32px 24px", minHeight: "100%" }}>
      {/* Page header */}
      <div style={{ marginBottom: 24 }}>
        <h1
          style={{
            fontSize: "1.875rem",
            fontWeight: 700,
            color: "var(--text)",
            margin: 0,
          }}
        >
          Kanban Board
        </h1>
        <p
          style={{
            fontSize: "0.9rem",
            color: "var(--muted)",
            marginTop: 4,
          }}
        >
          Visualize and manage task progress across stages
        </p>
      </div>

      {/* Loading state */}
      {isLoading ? (
        <div className="flex justify-center py-16">
          <MosaicSpinner label="Loading tasks..." />
        </div>
      ) : error !== null ? (
        /* Error state */
        <div
          style={{
            background: "var(--surface)",
            border: "1px solid var(--border)",
            borderRadius: "var(--r-lg)",
            padding: 32,
            textAlign: "center",
          }}
        >
          <p style={{ color: "var(--danger)", margin: "0 0 16px" }}>{error}</p>
          <button
            onClick={handleRetry}
            style={{
              padding: "8px 16px",
              background: "var(--danger)",
              border: "none",
              borderRadius: "var(--r)",
              color: "#fff",
              fontSize: "0.85rem",
              fontWeight: 500,
              cursor: "pointer",
            }}
          >
            Try again
          </button>
        </div>
      ) : tasks.length === 0 ? (
        /* Empty state */
        <div
          style={{
            background: "var(--surface)",
            border: "1px solid var(--border)",
            borderRadius: "var(--r-lg)",
            padding: 48,
            textAlign: "center",
          }}
        >
          <p style={{ color: "var(--muted)", margin: 0, fontSize: "0.9rem" }}>
            No tasks yet. Create some tasks to see them here.
          </p>
        </div>
      ) : (
        /* Board */
        <DragDropContext onDragEnd={handleDragEnd}>
          <div
            style={{
              display: "flex",
              gap: 16,
              overflowX: "auto",
              paddingBottom: 16,
              minHeight: 400,
            }}
          >
            {COLUMNS.map((col) => (
              <KanbanColumn key={col.status} config={col} tasks={grouped[col.status]} />
            ))}
          </div>
        </DragDropContext>
      )}
    </main>
  );
}
