import React, { useCallback, useEffect } from "react";
import {
  DragDropContext,
  Droppable,
  Draggable,
  type DropResult,
} from "@hello-pangea/dnd";

import { KanbanCard } from "./kanban-card";
import { KanbanColumnHeader } from "./kanban-column-header";
import { Task, TaskStatus } from "../types";
import { MemberAvatar } from "@/features/members/components/member-avatar";
import { snakeCaseToTitleCase } from "@/lib/utils";

type GroupByOption = "assignee" | "status" | "priority" | "labels" | "project";

interface DataKanbanGroupedProps {
  data: Task[];
  onChange: (
    tasks: {
      $id: string;
      status: TaskStatus;
      position: number;
    }[]
  ) => void;
  groupBy: GroupByOption;
}

const statusBoards: TaskStatus[] = [
  TaskStatus.BACKLOG,
  TaskStatus.TODO,
  TaskStatus.IN_PROGRESS,
  TaskStatus.IN_REVIEW,
  TaskStatus.DONE,
];

export const DataKanbanGrouped = ({ data, onChange, groupBy }: DataKanbanGroupedProps) => {
  const [kanbanColumns, setKanbanColumns] = React.useState<{ [key: string]: Task[] }>({});

  // Create kanban columns for assignee grouping (assignee-status combination)
  const createKanbanColumns = useCallback((tasks: Task[]): { [key: string]: Task[] } => {
    const columns: { [key: string]: Task[] } = {};
    
    if (groupBy === "assignee") {
      // Get unique assignees
      const assignees = Array.from(new Set(tasks.map(task => task.assignee?.name || "Unassigned")));
      
      // Create columns for each assignee-status combination
      assignees.forEach(assignee => {
        statusBoards.forEach(status => {
          const columnKey = `${assignee}-${status}`;
          columns[columnKey] = tasks
            .filter(task => (task.assignee?.name || "Unassigned") === assignee && task.status === status)
            .sort((a, b) => a.position - b.position);
        });
      });
    }
    
    return columns;
  }, [groupBy]);

  useEffect(() => {
    if (groupBy === "assignee") {
      const columns = createKanbanColumns(data);
      setKanbanColumns(columns);
    }
  }, [data, groupBy, createKanbanColumns]);

  const onDragEnd = useCallback(
    (result: DropResult) => {
      if (!result.destination) return;

      const { source, destination } = result;
      const sourceColumnKey = source.droppableId;
      const destColumnKey = destination.droppableId;

      // Extract assignee names from column keys
      const sourceAssignee = sourceColumnKey.split("-").slice(0, -1).join("-");
      const destAssignee = destColumnKey.split("-").slice(0, -1).join("-");

      // Prevent dragging between different assignees
      if (sourceAssignee !== destAssignee) {
        return;
      }

      let updatesPayload: {
        $id: string;
        status: TaskStatus;
        position: number;
      }[] = [];

      setKanbanColumns((prevColumns) => {
        const newColumns = { ...prevColumns };

        // Get source and destination arrays
        const sourceColumn = [...(newColumns[sourceColumnKey] || [])];
        const destColumn = sourceColumnKey === destColumnKey 
          ? sourceColumn 
          : [...(newColumns[destColumnKey] || [])];

        // Remove task from source
        const [movedTask] = sourceColumn.splice(source.index, 1);
        if (!movedTask) return prevColumns;

        // Extract status from columnKey (format: "assigneeName-status")
        const destParts = destColumnKey.split("-");
        const destinationStatus = destParts[destParts.length - 1] as TaskStatus;

        // Update task status
        const updatedMovedTask = {
          ...movedTask,
          status: destinationStatus,
        };

        // Add task to destination
        destColumn.splice(destination.index, 0, updatedMovedTask);

        // Update the column state
        newColumns[sourceColumnKey] = sourceColumn;
        if (sourceColumnKey !== destColumnKey) {
          newColumns[destColumnKey] = destColumn;
        }

        // Prepare update payload
        updatesPayload = [{
          $id: updatedMovedTask.id,
          status: destinationStatus,
          position: Math.min((destination.index + 1) * 1000, 1_000_000),
        }];

        // Update positions for affected tasks
        destColumn.forEach((task, index) => {
          if (task && task.id !== updatedMovedTask.id) {
            const newPosition = Math.min((index + 1) * 1000, 1_000_000);
            if (task.position !== newPosition) {
              updatesPayload.push({
                $id: task.id,
                status: task.status,
                position: newPosition,
              });
            }
          }
        });

        return newColumns;
      });

      onChange(updatesPayload);
    },
    [onChange]
  );

  if (groupBy === "assignee") {
    // Get unique assignees
    const assignees = Array.from(new Set(data.map(task => task.assignee?.name || "Unassigned")));

    return (
      <DragDropContext onDragEnd={onDragEnd}>
        <div className="space-y-6">
          {assignees.map((assignee) => {
            // Get all tasks for this assignee
            const assigneeTasks = data.filter(task => (task.assignee?.name || "Unassigned") === assignee);
            
            return (
              <div key={assignee} className="space-y-2">
                {/* Assignee Header */}
                <div className="px-3 py-2 flex items-center gap-2 bg-muted rounded-md">
                  <MemberAvatar name={assignee} className="size-6" />
                  <h3 className="text-sm font-medium">{assignee}</h3>
                  <div className="text-xs text-muted-foreground">
                    {assigneeTasks.length} tasks
                  </div>
                </div>
                
                {/* Normal Kanban Columns for this assignee */}
                <div className="flex overflow-x-auto gap-4">
                  {statusBoards.map((status) => {
                    const columnKey = `${assignee}-${status}`;
                    const tasks = kanbanColumns[columnKey] || [];
                    
                    return (
                      <div
                        key={status}
                        className="flex-1 mx-2 bg-muted p-1.5 rounded-md min-w-[200px]"
                      >
                        <KanbanColumnHeader
                          board={status}
                          taskCount={tasks.length}
                        />
                        
                        <Droppable droppableId={columnKey}>
                          {(provided) => (
                            <div
                              {...provided.droppableProps}
                              ref={provided.innerRef}
                              className="min-h-[200px] py-1.5"
                            >
                              {tasks.map((task, index) => (
                                <Draggable
                                  key={task.id}
                                  draggableId={task.id}
                                  index={index}
                                >
                                  {(provided) => (
                                    <div
                                      ref={provided.innerRef}
                                      {...provided.draggableProps}
                                      {...provided.dragHandleProps}
                                    >
                                      <KanbanCard task={task} />
                                    </div>
                                  )}
                                </Draggable>
                              ))}
                              {provided.placeholder}
                            </div>
                          )}
                        </Droppable>
                      </div>
                    );
                  })}
                </div>
              </div>
            );
          })}
        </div>
      </DragDropContext>
    );
  }

  // Fallback for other grouping types (should not be used)
  return (
    <div className="text-center py-8 text-muted-foreground">
      Grouping by {groupBy} is not supported in this view
    </div>
  );
}; 