import React, { useState, useCallback, useMemo, useEffect } from 'react';
import { GroupedVirtuoso } from 'react-virtuoso';
import {
  DndContext,
  DragEndEvent,
  DragOverEvent,
  DragOverlay,
  DragStartEvent,
  PointerSensor,
  useSensor,
  useSensors,
  KeyboardSensor,
  TouchSensor,
  closestCenter,
} from '@dnd-kit/core';
import {
  SortableContext,
  verticalListSortingStrategy,
  sortableKeyboardCoordinates,
} from '@dnd-kit/sortable';
import { useTranslation } from 'react-i18next';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import {
  selectAllTasksArray,
  selectGroups,
  selectGrouping,
  selectLoading,
  selectError,
  selectSelectedPriorities,
  selectSearch,
  fetchTasksV3,
  reorderTasksInGroup,
  moveTaskBetweenGroups,
} from '@/features/task-management/task-management.slice';
import {
  selectCurrentGrouping,
  selectCollapsedGroups,
  toggleGroupCollapsed,
} from '@/features/task-management/grouping.slice';
import {
  selectSelectedTaskIds,
  selectLastSelectedTaskId,
  selectIsTaskSelected,
  selectTask,
  deselectTask,
  toggleTaskSelection,
  selectRange,
  clearSelection,
} from '@/features/task-management/selection.slice';
import TaskRowWithSubtasks from './TaskRowWithSubtasks';
import TaskGroupHeader from './TaskGroupHeader';
import { Task, TaskGroup } from '@/types/task-management.types';
import { RootState } from '@/app/store';
import { TaskListField } from '@/types/task-list-field.types';
import { useParams } from 'react-router-dom';
import ImprovedTaskFilters from '@/components/task-management/improved-task-filters';
import OptimizedBulkActionBar from '@/components/task-management/optimized-bulk-action-bar';
import { useTaskSocketHandlers } from '@/hooks/useTaskSocketHandlers';
import { HolderOutlined } from '@ant-design/icons';
import { COLUMN_KEYS } from '@/features/tasks/tasks.slice';

// Base column configuration
const BASE_COLUMNS = [
  { id: 'dragHandle', label: '', width: '32px', isSticky: true, key: 'dragHandle' },
  { id: 'checkbox', label: '', width: '40px', isSticky: true, key: 'checkbox' },
  { id: 'taskKey', label: 'keyColumn', width: '100px', key: COLUMN_KEYS.KEY },
  { id: 'title', label: 'taskColumn', width: '470px', isSticky: true, key: COLUMN_KEYS.NAME },
  { id: 'status', label: 'statusColumn', width: '120px', key: COLUMN_KEYS.STATUS },
  { id: 'assignees', label: 'assigneesColumn', width: '150px', key: COLUMN_KEYS.ASSIGNEES },
  { id: 'priority', label: 'priorityColumn', width: '120px', key: COLUMN_KEYS.PRIORITY },
  { id: 'dueDate', label: 'dueDateColumn', width: '120px', key: COLUMN_KEYS.DUE_DATE },
  { id: 'progress', label: 'progressColumn', width: '120px', key: COLUMN_KEYS.PROGRESS },
  { id: 'labels', label: 'labelsColumn', width: 'auto', key: COLUMN_KEYS.LABELS },
  { id: 'phase', label: 'phaseColumn', width: '120px', key: COLUMN_KEYS.PHASE },
  { id: 'timeTracking', label: 'timeTrackingColumn', width: '120px', key: COLUMN_KEYS.TIME_TRACKING },
  { id: 'estimation', label: 'estimationColumn', width: '120px', key: COLUMN_KEYS.ESTIMATION },
  { id: 'startDate', label: 'startDateColumn', width: '120px', key: COLUMN_KEYS.START_DATE },
  { id: 'dueTime', label: 'dueTimeColumn', width: '120px', key: COLUMN_KEYS.DUE_TIME },
  { id: 'completedDate', label: 'completedDateColumn', width: '120px', key: COLUMN_KEYS.COMPLETED_DATE },
  { id: 'createdDate', label: 'createdDateColumn', width: '120px', key: COLUMN_KEYS.CREATED_DATE },
  { id: 'lastUpdated', label: 'lastUpdatedColumn', width: '120px', key: COLUMN_KEYS.LAST_UPDATED },
  { id: 'reporter', label: 'reporterColumn', width: '120px', key: COLUMN_KEYS.REPORTER },
];

type ColumnStyle = {
  width: string;
  position?: 'static' | 'relative' | 'absolute' | 'sticky' | 'fixed';
  left?: number;
  backgroundColor?: string;
  zIndex?: number;
  flexShrink?: number;
};

const TaskListV2: React.FC = () => {
  const dispatch = useAppDispatch();
  const { projectId: urlProjectId } = useParams();
  const { t } = useTranslation('task-list-table');

  // Drag and drop state
  const [activeId, setActiveId] = useState<string | null>(null);

  // Configure sensors for drag and drop
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8,
      },
    }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
    useSensor(TouchSensor, {
      activationConstraint: {
        delay: 250,
        tolerance: 5,
      },
    })
  );

  // Using Redux state for collapsedGroups instead of local state
  const collapsedGroups = useAppSelector(selectCollapsedGroups);

  // Selectors
  const allTasks = useAppSelector(selectAllTasksArray); // Renamed to allTasks for clarity
  const groups = useAppSelector(selectGroups);
  const grouping = useAppSelector(selectGrouping);
  const loading = useAppSelector(selectLoading);
  const error = useAppSelector(selectError);
  const selectedPriorities = useAppSelector(selectSelectedPriorities);
  const searchQuery = useAppSelector(selectSearch);
  const currentGrouping = useAppSelector(selectCurrentGrouping);
  const selectedTaskIds = useAppSelector(selectSelectedTaskIds);
  const lastSelectedTaskId = useAppSelector(selectLastSelectedTaskId);

  const fields = useAppSelector(state => state.taskManagementFields) || [];

  // Enable real-time updates via socket handlers
  useTaskSocketHandlers();

  // Filter visible columns based on fields
  const visibleColumns = useMemo(() => {
    return BASE_COLUMNS.filter(column => {
      // Always show drag handle and title (sticky columns)
      if (column.isSticky) return true;
      // Check if field is visible for all other columns (including task key)
      const field = fields.find(f => f.key === column.key);
      return field?.visible ?? false;
    });
  }, [fields]);

  // Effects
  useEffect(() => {
    if (urlProjectId) {
      dispatch(fetchTasksV3(urlProjectId));
    }
  }, [dispatch, urlProjectId]);

  // Handlers
  const handleTaskSelect = useCallback(
    (taskId: string, event: React.MouseEvent) => {
      if (event.ctrlKey || event.metaKey) {
        dispatch(toggleTaskSelection(taskId));
      } else if (event.shiftKey && lastSelectedTaskId) {
        const taskIds = allTasks.map(t => t.id); // Use allTasks here
        const startIdx = taskIds.indexOf(lastSelectedTaskId);
        const endIdx = taskIds.indexOf(taskId);
        const rangeIds = taskIds.slice(Math.min(startIdx, endIdx), Math.max(startIdx, endIdx) + 1);
        dispatch(selectRange(rangeIds));
      } else {
        dispatch(clearSelection());
        dispatch(selectTask(taskId));
      }
    },
    [dispatch, lastSelectedTaskId, allTasks]
  );

  const handleGroupCollapse = useCallback(
    (groupId: string) => {
      dispatch(toggleGroupCollapsed(groupId)); // Dispatch Redux action to toggle collapsed state
    },
    [dispatch]
  );

  // Drag and drop handlers
  const handleDragStart = useCallback((event: DragStartEvent) => {
    setActiveId(event.active.id as string);
  }, []);

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

      if (!over) return;

      const activeId = active.id;
      const overId = over.id;

      // Find the active task and the item being dragged over
      const activeTask = allTasks.find(task => task.id === activeId);
      if (!activeTask) return;

      // Check if we're dragging over a task or a group
      const overTask = allTasks.find(task => task.id === overId);
      const overGroup = groups.find(group => group.id === overId);

      // Find the groups
      const activeGroup = groups.find(group => group.taskIds.includes(activeTask.id));
      let targetGroup = overGroup;

      if (overTask) {
        targetGroup = groups.find(group => group.taskIds.includes(overTask.id));
      }

      if (!activeGroup || !targetGroup) return;

      // If dragging to a different group, we need to handle cross-group movement
      if (activeGroup.id !== targetGroup.id) {
        console.log('Cross-group drag detected:', {
          activeTask: activeTask.id,
          fromGroup: activeGroup.id,
          toGroup: targetGroup.id,
        });
      }
    },
    [allTasks, groups]
  );

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

      if (!over || active.id === over.id) {
        return;
      }

      const activeId = active.id;
      const overId = over.id;

      // Find the active task
      const activeTask = allTasks.find(task => task.id === activeId);
      if (!activeTask) {
        console.error('Active task not found:', activeId);
        return;
      }

      // Find the groups
      const activeGroup = groups.find(group => group.taskIds.includes(activeTask.id));
      if (!activeGroup) {
        console.error('Could not find active group for task:', activeId);
        return;
      }

      // Check if we're dropping on a task or a group
      const overTask = allTasks.find(task => task.id === overId);
      const overGroup = groups.find(group => group.id === overId);

      let targetGroup = overGroup;
      let insertIndex = 0;

      if (overTask) {
        // Dropping on a task
        targetGroup = groups.find(group => group.taskIds.includes(overTask.id));
        if (targetGroup) {
          insertIndex = targetGroup.taskIds.indexOf(overTask.id);
        }
      } else if (overGroup) {
        // Dropping on a group (at the end)
        targetGroup = overGroup;
        insertIndex = targetGroup.taskIds.length;
      }

      if (!targetGroup) {
        console.error('Could not find target group');
        return;
      }

      const isCrossGroup = activeGroup.id !== targetGroup.id;
      const activeIndex = activeGroup.taskIds.indexOf(activeTask.id);

      console.log('Drag operation:', {
        activeId,
        overId,
        activeTask: activeTask.name || activeTask.title,
        activeGroup: activeGroup.id,
        targetGroup: targetGroup.id,
        activeIndex,
        insertIndex,
        isCrossGroup,
      });

      if (isCrossGroup) {
        // Moving task between groups
        console.log('Moving task between groups:', {
          task: activeTask.name || activeTask.title,
          from: activeGroup.title,
          to: targetGroup.title,
          newPosition: insertIndex,
        });

        // Move task to the target group
        dispatch(
          moveTaskBetweenGroups({
            taskId: activeId as string,
            sourceGroupId: activeGroup.id,
            targetGroupId: targetGroup.id,
          })
        );

        // Reorder task within target group at drop position
        dispatch(
          reorderTasksInGroup({
            sourceTaskId: activeId as string,
            destinationTaskId: over.id as string,
            sourceGroupId: activeGroup.id,
            destinationGroupId: targetGroup.id,
          })
        );
      } else {
        // Reordering within the same group
        console.log('Reordering task within same group:', {
          task: activeTask.name || activeTask.title,
          group: activeGroup.title,
          from: activeIndex,
          to: insertIndex,
        });

        if (activeIndex !== insertIndex) {
          // Reorder task within same group at drop position
          dispatch(
            reorderTasksInGroup({
              sourceTaskId: activeId as string,
              destinationTaskId: over.id as string,
              sourceGroupId: activeGroup.id,
              destinationGroupId: activeGroup.id,
            })
          );
        }
      }
    },
    [allTasks, groups]
  );

  // Bulk action handlers
  const handleClearSelection = useCallback(() => {
    dispatch(clearSelection());
  }, [dispatch]);

  const handleBulkStatusChange = useCallback(async (statusId: string) => {
    // TODO: Implement bulk status change
    console.log('Bulk status change:', statusId);
  }, []);

  const handleBulkPriorityChange = useCallback(async (priorityId: string) => {
    // TODO: Implement bulk priority change
    console.log('Bulk priority change:', priorityId);
  }, []);

  const handleBulkPhaseChange = useCallback(async (phaseId: string) => {
    // TODO: Implement bulk phase change
    console.log('Bulk phase change:', phaseId);
  }, []);

  const handleBulkAssignToMe = useCallback(async () => {
    // TODO: Implement bulk assign to me
    console.log('Bulk assign to me');
  }, []);

  const handleBulkAssignMembers = useCallback(async (memberIds: string[]) => {
    // TODO: Implement bulk assign members
    console.log('Bulk assign members:', memberIds);
  }, []);

  const handleBulkAddLabels = useCallback(async (labelIds: string[]) => {
    // TODO: Implement bulk add labels
    console.log('Bulk add labels:', labelIds);
  }, []);

  const handleBulkArchive = useCallback(async () => {
    // TODO: Implement bulk archive
    console.log('Bulk archive');
  }, []);

  const handleBulkDelete = useCallback(async () => {
    // TODO: Implement bulk delete
    console.log('Bulk delete');
  }, []);

  const handleBulkDuplicate = useCallback(async () => {
    // TODO: Implement bulk duplicate
    console.log('Bulk duplicate');
  }, []);

  const handleBulkExport = useCallback(async () => {
    // TODO: Implement bulk export
    console.log('Bulk export');
  }, []);

  const handleBulkSetDueDate = useCallback(async (date: string) => {
    // TODO: Implement bulk set due date
    console.log('Bulk set due date:', date);
  }, []);

  // Memoized values for GroupedVirtuoso
  const virtuosoGroups = useMemo(() => {
    let currentTaskIndex = 0;
    return groups.map(group => {
      const isCurrentGroupCollapsed = collapsedGroups.has(group.id);

      // Order tasks according to group.taskIds array to maintain proper order
      const visibleTasksInGroup = isCurrentGroupCollapsed
        ? []
        : group.taskIds
            .map(taskId => allTasks.find(task => task.id === taskId))
            .filter((task): task is Task => task !== undefined); // Type guard to filter out undefined tasks

      const tasksForVirtuoso = visibleTasksInGroup.map(task => ({
        ...task,
        originalIndex: allTasks.indexOf(task),
      }));

      const groupData = {
        ...group,
        tasks: tasksForVirtuoso,
        startIndex: currentTaskIndex,
        count: tasksForVirtuoso.length,
        // Add actual task count for display purposes (regardless of collapsed state)
        actualCount: group.taskIds.length,
      };
      currentTaskIndex += tasksForVirtuoso.length;
      return groupData;
    });
  }, [groups, allTasks, collapsedGroups]);

  const virtuosoGroupCounts = useMemo(() => {
    return virtuosoGroups.map(group => group.count);
  }, [virtuosoGroups]);

  const virtuosoItems = useMemo(() => {
    return virtuosoGroups.flatMap(group => group.tasks);
  }, [virtuosoGroups]);

  // Memoize column headers to prevent unnecessary re-renders
  const columnHeaders = useMemo(
    () => (
      <div className="flex items-center px-4 py-2" style={{ minWidth: 'max-content' }}>
        {visibleColumns.map(column => {
          const columnStyle: ColumnStyle = {
            width: column.width,
            flexShrink: 0, // Prevent columns from shrinking
            // Add specific styling for labels column with auto width
            ...(column.id === 'labels' && column.width === 'auto'
              ? {
                  minWidth: '200px', // Ensure minimum width for labels
                  flexGrow: 1, // Allow it to grow
                }
              : {}),
          };

          return (
            <div
              key={column.id}
              className="text-xs font-medium text-gray-500 dark:text-gray-400"
              style={columnStyle}
            >
              {column.id === 'dragHandle' ? (
                <span></span> // Empty space for drag handle column header
              ) : column.id === 'checkbox' ? (
                <span></span> // Empty for checkbox column header
              ) : (
                t(column.label)
              )}
            </div>
          );
        })}
      </div>
    ),
    [visibleColumns, t]
  );

  // Render functions
  const renderGroup = useCallback(
    (groupIndex: number) => {
      const group = virtuosoGroups[groupIndex];
      const isGroupEmpty = group.count === 0;

      return (
        <div className={groupIndex > 0 ? 'mt-2' : ''}>
          <TaskGroupHeader
            group={{
              id: group.id,
              name: group.title,
              count: group.actualCount, // Use actualCount instead of count for display
              color: group.color,
            }}
            isCollapsed={collapsedGroups.has(group.id)}
            onToggle={() => handleGroupCollapse(group.id)}
          />
          {/* Empty group drop zone */}
          {isGroupEmpty && !collapsedGroups.has(group.id) && (
            <div className="px-4 py-8 text-center text-gray-400 dark:text-gray-500 border-2 border-dashed border-transparent hover:border-blue-300 transition-colors">
              <div className="text-sm">Drop tasks here</div>
            </div>
          )}
        </div>
      );
    },
    [virtuosoGroups, collapsedGroups, handleGroupCollapse]
  );

  const renderTask = useCallback(
    (taskIndex: number) => {
      const task = virtuosoItems[taskIndex]; // Get task from the flattened virtuosoItems
      if (!task || !urlProjectId) return null; // Should not happen if logic is correct
      return (
        <TaskRowWithSubtasks
          taskId={task.id}
          projectId={urlProjectId}
          visibleColumns={visibleColumns}
        />
      );
    },
    [virtuosoItems, visibleColumns]
  );

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragStart={handleDragStart}
      onDragOver={handleDragOver}
      onDragEnd={handleDragEnd}
    >
      <div className="flex flex-col h-screen bg-white dark:bg-gray-900">
        {/* Task Filters */}
        <div className="flex-none px-4 py-3">
          <ImprovedTaskFilters position="list" />
        </div>

        {/* Table Container with synchronized horizontal scrolling */}
        <div className="flex-1 overflow-x-auto">
          <div className="min-w-max flex flex-col h-full">
            {/* Column Headers - Fixed at top */}
            <div className="flex-none border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800">
              {columnHeaders}
            </div>

            {/* Task List - Scrollable content */}
            <div className="flex-1">
              <SortableContext
                items={virtuosoItems
                  .filter(task => !task.parent_task_id)
                  .map(task => task.id)
                  .filter((id): id is string => id !== undefined)}
                strategy={verticalListSortingStrategy}
              >
                <GroupedVirtuoso
                  style={{ height: 'calc(100vh - 200px)' }}
                  groupCounts={virtuosoGroupCounts}
                  groupContent={renderGroup}
                  itemContent={renderTask}
                  components={{
                    List: React.forwardRef<
                      HTMLDivElement,
                      { style?: React.CSSProperties; children?: React.ReactNode }
                    >(({ style, children }, ref) => (
                      <div ref={ref} style={style || {}} className="virtuoso-list-container">
                        {children}
                      </div>
                    )),
                  }}
                />
              </SortableContext>
            </div>
          </div>
        </div>

        {/* Drag Overlay */}
        <DragOverlay dropAnimation={null}>
          {activeId ? (
            <div className="bg-white dark:bg-gray-800 shadow-xl rounded-md border-2 border-blue-400 opacity-95">
              <div className="px-4 py-3">
                <div className="flex items-center gap-3">
                  <HolderOutlined className="text-blue-500" />
                  <div>
                    <div className="text-sm font-medium text-gray-900 dark:text-white">
                      {allTasks.find(task => task.id === activeId)?.name ||
                        allTasks.find(task => task.id === activeId)?.title ||
                        'Task'}
                    </div>
                    <div className="text-xs text-gray-500 dark:text-gray-400">
                      {allTasks.find(task => task.id === activeId)?.task_key}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          ) : null}
        </DragOverlay>

        {/* Bulk Action Bar */}
        {selectedTaskIds.length > 0 && urlProjectId && (
          <OptimizedBulkActionBar
            selectedTaskIds={selectedTaskIds}
            totalSelected={selectedTaskIds.length}
            projectId={urlProjectId}
            onClearSelection={handleClearSelection}
            onBulkStatusChange={handleBulkStatusChange}
            onBulkPriorityChange={handleBulkPriorityChange}
            onBulkPhaseChange={handleBulkPhaseChange}
            onBulkAssignToMe={handleBulkAssignToMe}
            onBulkAssignMembers={handleBulkAssignMembers}
            onBulkAddLabels={handleBulkAddLabels}
            onBulkArchive={handleBulkArchive}
            onBulkDelete={handleBulkDelete}
            onBulkDuplicate={handleBulkDuplicate}
            onBulkExport={handleBulkExport}
            onBulkSetDueDate={handleBulkSetDueDate}
          />
        )}
      </div>
    </DndContext>
  );
};

export default TaskListV2;
