import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
import { View, Text, StyleSheet, FlatList, TouchableOpacity, Animated, RefreshControl, Alert } from 'react-native';
import { useRouter } from 'expo-router';
import { useTasks } from '@/hooks/useTasks';
import { TaskItem } from './TaskItem';
import { SubtaskItem } from './SubtaskItem';
import { TaskData, SubtaskData } from '@/types';
import { useCategories, useDatabase } from '@/hooks/useDatabase';
import { useSettings } from '@/theme';
import { OptionPickerModal } from './OptionPickerModal';
import { TaskOverflowMenu } from './TaskOverflowMenu';
import { TaskDeleteModal } from './TaskDeleteModal';
import {
  toggleTaskComplete,
  deleteTask,
  duplicateTask,
  setTaskCategory,
  setTaskPriority,
  setTaskCompleted,
  deleteTaskOccurrences,
  convertTaskToSubtask,
  toggleSubtaskComplete,
  TaskDeleteScope,
} from '@/utils/taskActions';
import { PRIORITY_LABELS } from '@/constants';
import { Q } from '@nozbe/watermelondb';
import Svg, { Path } from 'react-native-svg';

interface TaskListProps {
  categoryId?: string;
  onSelectionChange?: (active: boolean) => void;
}

const PRIORITY_RANK: Record<string, number> = { none: 0, low: 1, medium: 2, high: 3, critical: 4 };

export function TaskList({ categoryId = 'all', onSelectionChange }: TaskListProps) {
  const router = useRouter();
  const { theme, sortBy } = useSettings();
  const { collections } = useDatabase();
  const categories = useCategories();

  const { tasks, loading } = useTasks(categoryId, false);
  const { tasks: completedTasks } = useTasks(categoryId, true);

  const [refreshing, setRefreshing] = useState(false);
  const [selectionMode, setSelectionMode] = useState(false);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [menuTaskId, setMenuTaskId] = useState<string | null>(null);
  const [deleteTaskId, setDeleteTaskId] = useState<string | null>(null);
  const [picker, setPicker] = useState<null | { type: 'category' | 'priority'; taskId?: string }>(null);
  const [hoverTaskId, setHoverTaskId] = useState<string | null>(null);
  const [expandedTasks, setExpandedTasks] = useState<Set<string>>(new Set());
  const [subtasksMap, setSubtasksMap] = useState<Map<string, SubtaskData[]>>(new Map());
  const itemRefs = useRef<Map<string, View>>(new Map());
  const dragStateRef = useRef<{ taskId: string; positions: Record<string, { top: number; bottom: number }> } | null>(null);

  const allTasks = useMemo(() => [...tasks, ...completedTasks], [tasks, completedTasks]);

  const sortedTasks = useMemo(() => {
    const sorted = [...tasks];
    switch (sortBy) {
      case 'date':
        sorted.sort((a, b) => (a.dueDate || Number.MAX_SAFE_INTEGER) - (b.dueDate || Number.MAX_SAFE_INTEGER));
        break;
      case 'priority':
        sorted.sort((a, b) => PRIORITY_RANK[b.priority] - PRIORITY_RANK[a.priority]);
        break;
      case 'alpha':
        sorted.sort((a, b) => a.title.localeCompare(b.title));
        break;
      case 'created':
        sorted.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
        break;
    }
    return sorted;
  }, [tasks, sortBy]);

  const menuTask = useMemo(
    () => allTasks.find((t) => t.id === menuTaskId) ?? null,
    [allTasks, menuTaskId]
  );

  const deleteTarget = useMemo(
    () => allTasks.find((t) => t.id === deleteTaskId) ?? null,
    [allTasks, deleteTaskId]
  );

  const onRefresh = useCallback(() => {
    setRefreshing(true);
    setTimeout(() => setRefreshing(false), 600);
  }, []);

  const exitSelection = useCallback(() => {
    setSelectionMode(false);
    setSelectedIds(new Set());
    onSelectionChange?.(false);
  }, [onSelectionChange]);

  const enterSelection = useCallback((taskId: string) => {
    setSelectionMode(true);
    setSelectedIds(new Set([taskId]));
    onSelectionChange?.(true);
  }, [onSelectionChange]);

  const toggleSelect = useCallback((taskId: string) => {
    setSelectedIds((prev) => {
      const next = new Set(prev);
      if (next.has(taskId)) {
        next.delete(taskId);
      } else {
        next.add(taskId);
      }
      if (next.size === 0) {
        setSelectionMode(false);
        onSelectionChange?.(false);
      }
      return next;
    });
  }, [onSelectionChange]);

  const refreshAll = useCallback(() => {}, []);

  const handleEdit = useCallback((taskId: string) => {
    router.push({ pathname: '/task-detail', params: { id: taskId } });
  }, [router]);

  const handleToggle = useCallback(async (taskId: string) => {
    await toggleTaskComplete(taskId);
    refreshAll();
  }, [refreshAll]);

  const fetchSubtasks = useCallback(async (taskId: string) => {
    const subs = await collections.subtasks.query(Q.where('task_id', taskId)).fetch();
    const mapped: SubtaskData[] = subs.map((s: any) => ({
      id: s.id,
      taskId: s.taskId,
      title: s.title,
      description: s.description || '',
      priority: (s.priority || 'none') as SubtaskData['priority'],
      completed: s.completed,
      dueDate: s.dueDate || 0,
      dueTime: s.dueTime || '',
      endTime: s.endTime || '',
      allDay: s.allDay ?? false,
      repeat: (s.repeat || 'none') as SubtaskData['repeat'],
      repeatInterval: s.repeatInterval ?? 1,
      repeatDays: s.repeatDays || '',
      seriesId: s.seriesId || '',
      reminder: (s.reminder || 'none') as SubtaskData['reminder'],
      assigneeId: s.assigneeId ?? null,
      order: s.order,
    }));
    setSubtasksMap((prev) => new Map(prev).set(taskId, mapped));
    return mapped;
  }, [collections.subtasks]);

  const toggleExpand = useCallback(async (taskId: string) => {
    setExpandedTasks((prev) => {
      const next = new Set(prev);
      if (next.has(taskId)) {
        next.delete(taskId);
      } else {
        next.add(taskId);
      }
      return next;
    });

    const isCurrentlyExpanded = expandedTasks.has(taskId);
    if (isCurrentlyExpanded) {
      setSubtasksMap((prev) => {
        const next = new Map(prev);
        next.delete(taskId);
        return next;
      });
    } else {
      await fetchSubtasks(taskId);
    }
  }, [expandedTasks, fetchSubtasks]);

  const handleSubtaskToggle = useCallback(async (subtaskId: string, taskId: string) => {
    await toggleSubtaskComplete(subtaskId);
    await fetchSubtasks(taskId);
  }, [fetchSubtasks]);

  const handleDeleteOne = useCallback((taskId: string) => {
    setDeleteTaskId(taskId);
  }, []);

  const handleDeleteScope = useCallback(async (scope: TaskDeleteScope) => {
    const taskId = deleteTaskId;
    if (!taskId) return;
    setDeleteTaskId(null);
    await deleteTaskOccurrences(taskId, scope);
    refreshAll();
  }, [deleteTaskId, refreshAll]);

  const handleDuplicate = useCallback(async (taskId: string) => {
    await duplicateTask(taskId);
    refreshAll();
  }, [refreshAll]);

  const handleBulkDelete = useCallback(() => {
    Alert.alert(`Delete ${selectedIds.size} task${selectedIds.size > 1 ? 's' : ''}?`, 'This cannot be undone.', [
      { text: 'Cancel', style: 'cancel' },
      {
        text: 'Delete',
        style: 'destructive',
        onPress: async () => {
          for (const taskId of selectedIds) {
            await deleteTask(taskId);
          }
          exitSelection();
          refreshAll();
        },
      },
    ]);
  }, [selectedIds, exitSelection, refreshAll]);

  const handleBulkComplete = useCallback(async () => {
    for (const taskId of selectedIds) {
      await setTaskCompleted(taskId, true);
    }
    exitSelection();
    refreshAll();
  }, [selectedIds, exitSelection, refreshAll]);

  const handleSingleCategory = useCallback(async (value: string) => {
    if (picker?.taskId) {
      await setTaskCategory(picker.taskId, value);
      refreshAll();
    }
  }, [picker, refreshAll]);

  const handleSinglePriority = useCallback(async (value: string) => {
    if (picker?.taskId) {
      await setTaskPriority(picker.taskId, value as TaskData['priority']);
      refreshAll();
    }
  }, [picker, refreshAll]);

  const measureItems = useCallback(async () => {
    const positions: Record<string, { top: number; bottom: number }> = {};
    const entries = Array.from(itemRefs.current.entries());
    await Promise.all(entries.map(([id, ref]) => {
      return new Promise<void>((resolve) => {
        ref?.measureInWindow((_x, y, _w, h) => {
          positions[id] = { top: y, bottom: y + h };
          resolve();
        });
      });
    }));
    return positions;
  }, []);

  const findHoverTarget = useCallback((absoluteY: number, draggedId: string, positions: Record<string, { top: number; bottom: number }>) => {
    for (const [id, p] of Object.entries(positions)) {
      if (id === draggedId) continue;
      if (absoluteY >= p.top && absoluteY <= p.bottom) {
        return id;
      }
    }
    return null;
  }, []);

  const handleDragStart = useCallback(async (taskId: string) => {
    dragStateRef.current = { taskId, positions: await measureItems() };
  }, [measureItems]);

  const handleDragUpdate = useCallback((absoluteY: number) => {
    const state = dragStateRef.current;
    if (!state) return;
    const target = findHoverTarget(absoluteY, state.taskId, state.positions);
    setHoverTaskId((prev) => (prev === target ? prev : target));
  }, [findHoverTarget]);

  const handleDragEnd = useCallback((absoluteY: number) => {
    const state = dragStateRef.current;
    dragStateRef.current = null;
    setHoverTaskId(null);
    if (!state) return;

    const target = findHoverTarget(absoluteY, state.taskId, state.positions);
    if (target) {
      (async () => {
        await convertTaskToSubtask(state.taskId, target);
        refreshAll();
      })();
    }
  }, [findHoverTarget, refreshAll]);

  if (loading && !refreshing) {
    return (
      <View style={styles.loadingContainer}>
        <Text style={[styles.loadingText, { color: theme.textFaint }]}>Loading tasks...</Text>
      </View>
    );
  }

  const priorityOptions = Object.entries(PRIORITY_LABELS).map(([value, label]) => ({ value, label }));

  return (
    <View style={styles.container}>
      <Animated.FlatList
        data={sortedTasks}
        keyExtractor={(item) => item.id}
         renderItem={({ item }) => {
           const isExpanded = expandedTasks.has(item.id);
           const itemSubtasks = subtasksMap.get(item.id) ?? [];
           return (
           <View
             ref={(ref) => {
               if (ref) {
                 itemRefs.current.set(item.id, ref);
               } else {
                 itemRefs.current.delete(item.id);
               }
             }}
           >
            <TaskItem
              task={item as TaskData}
              onToggle={() => handleToggle(item.id)}
              onDelete={() => handleDeleteOne(item.id)}
              onPress={() => selectionMode ? toggleSelect(item.id) : toggleExpand(item.id)}
              onLongPress={selectionMode ? undefined : () => enterSelection(item.id)}
              onMenuOpen={() => setMenuTaskId(item.id)}
              selected={selectedIds.has(item.id)}
              selectionMode={selectionMode}
              expanded={isExpanded}
              draggable
              hovered={hoverTaskId === item.id}
              onDragStart={() => handleDragStart(item.id)}
              onDragUpdate={handleDragUpdate}
              onDragEnd={handleDragEnd}
            />
             {isExpanded && itemSubtasks.length > 0 && (
               <View style={styles.subtaskList}>
                 {itemSubtasks
                   .slice()
                   .sort((a, b) => a.order - b.order)
                   .map((sub) => (
                     <SubtaskItem
                       key={sub.id}
                       subtask={sub}
                       onToggle={() => handleSubtaskToggle(sub.id, item.id)}
                     />
                   ))}
               </View>
             )}
           </View>
          );
        }}
        ItemSeparatorComponent={() => <View style={styles.separator} />}
        ListHeaderComponent={
          sortedTasks.length === 0 && completedTasks.length === 0 ? (
            <View style={styles.emptyState}>
              <Text style={[styles.emptyText, { color: theme.textSecondary }]}>No tasks yet</Text>
              <Text style={[styles.emptySubtext, { color: theme.textMuted }]}>Tap + to add your first task</Text>
            </View>
          ) : sortedTasks.length === 0 ? (
            <View style={styles.emptyState}>
              <Text style={[styles.emptyText, { color: theme.textSecondary }]}>All caught up!</Text>
              <Text style={[styles.emptySubtext, { color: theme.textMuted }]}>No pending tasks</Text>
            </View>
          ) : null
        }
        ListFooterComponent={
          completedTasks.length > 0 ? (
            <CompletedSection
              tasks={completedTasks}
              onToggle={(task) => handleToggle(task.id)}
              onDelete={(task) => handleDeleteOne(task.id)}
              onMenuOpen={(task) => setMenuTaskId(task.id)}
              onLongPress={(task) => enterSelection(task.id)}
              selectionMode={selectionMode}
              selectedIds={selectedIds}
              onSelect={(taskId) => toggleSelect(taskId)}
            />
          ) : null
        }
        refreshControl={
          <RefreshControl
            refreshing={refreshing}
            onRefresh={onRefresh}
            tintColor={theme.accent}
            colors={[theme.accent]}
            progressBackgroundColor={theme.card}
          />
        }
        contentContainerStyle={styles.listContent}
      />

      <TaskDeleteModal
        visible={deleteTarget !== null}
        taskId={deleteTarget?.id ?? null}
        taskTitle={deleteTarget?.title}
        isRepeating={deleteTarget ? deleteTarget.repeat !== 'none' : false}
        onClose={() => setDeleteTaskId(null)}
        onDelete={handleDeleteScope}
      />

      <TaskOverflowMenu
        visible={menuTask !== null}
        task={menuTask}
        onClose={() => setMenuTaskId(null)}
        onEdit={() => menuTask && handleEdit(menuTask.id)}
        onDelete={() => menuTask && handleDeleteOne(menuTask.id)}
        onDuplicate={() => menuTask && handleDuplicate(menuTask.id)}
        onToggleComplete={() => menuTask && handleToggle(menuTask.id)}
        onChangeCategory={() => menuTask && setPicker({ type: 'category', taskId: menuTask.id })}
        onChangePriority={() => menuTask && setPicker({ type: 'priority', taskId: menuTask.id })}
      />

      <OptionPickerModal
        visible={picker?.type === 'category'}
        title="Change Category"
        options={categories.map((c) => ({ value: c.id, label: c.name, color: c.color }))}
        selectedValue={menuTask?.categoryId}
        onSelect={handleSingleCategory}
        onClose={() => setPicker(null)}
      />

      <OptionPickerModal
        visible={picker?.type === 'priority'}
        title="Change Priority"
        options={priorityOptions}
        selectedValue={menuTask?.priority}
        onSelect={handleSinglePriority}
        onClose={() => setPicker(null)}
      />

      {selectionMode && (
        <View style={[styles.selectionBar, { backgroundColor: theme.sheetBg, borderTopColor: theme.border }]}>
          <TouchableOpacity onPress={exitSelection} style={styles.selectionCancel} activeOpacity={0.7}>
            <Svg width={20} height={20} viewBox="0 0 24 24">
              <Path d="M18 6L6 18M6 6l12 12" stroke={theme.textFaint} strokeWidth={2} strokeLinecap="round" />
            </Svg>
            <Text style={[styles.selectionCancelText, { color: theme.textFaint }]}>Cancel</Text>
          </TouchableOpacity>
          <Text style={[styles.selectionCount, { color: theme.text }]}>{selectedIds.size} selected</Text>
          <View style={styles.selectionActions}>
            <SelectionButton label="Complete" color="#43A047" onPress={handleBulkComplete} />
            <SelectionButton label="Delete" color="#E53935" onPress={handleBulkDelete} />
          </View>
        </View>
      )}
    </View>
  );
}

function SelectionButton({ label, color, onPress }: { label: string; color: string; onPress: () => void }) {
  const { theme } = useSettings();
  return (
    <TouchableOpacity
      style={[styles.selectionButton, { backgroundColor: color }]}
      onPress={onPress}
      activeOpacity={0.8}
    >
      <Text style={styles.selectionButtonText}>{label}</Text>
    </TouchableOpacity>
  );
}

interface CompletedSectionProps {
  tasks: TaskData[];
  onToggle: (task: TaskData) => void;
  onDelete: (task: TaskData) => void;
  onMenuOpen: (task: TaskData) => void;
  onLongPress: (task: TaskData) => void;
  selectionMode: boolean;
  selectedIds: Set<string>;
  onSelect: (taskId: string) => void;
}

function CompletedSection({ tasks, onToggle, onDelete, onMenuOpen, onLongPress, selectionMode, selectedIds, onSelect }: CompletedSectionProps) {
  const { theme } = useSettings();
  const [expanded, setExpanded] = useState(false);

  return (
    <View style={styles.completedSection}>
      <TouchableOpacity
        style={styles.completedHeader}
        onPress={() => setExpanded(!expanded)}
      >
        <Text style={[styles.completedTitle, { color: theme.textFaint }]}>
          Completed ({tasks.length})
        </Text>
        <Text style={[styles.completedToggle, { color: theme.accent }]}>
          {expanded ? 'Hide' : 'Show'}
        </Text>
      </TouchableOpacity>
      {expanded && (
        <View style={styles.completedList}>
          {tasks.map((task) => (
            <TaskItem
              key={task.id}
              task={task}
              onToggle={() => onToggle(task)}
              onDelete={() => onDelete(task)}
              onPress={() => {}}
              onLongPress={() => onLongPress(task)}
              onMenuOpen={() => onMenuOpen(task)}
              selected={selectedIds.has(task.id)}
              selectionMode={selectionMode}
              completedSection
            />
          ))}
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  listContent: {
    paddingHorizontal: 16,
    paddingTop: 2,
    paddingBottom: 100,
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  loadingText: {
    fontSize: 16,
  },
  separator: {
    height: 8,
  },
  subtaskList: {
    paddingLeft: 8,
    paddingRight: 4,
  },
  emptyState: {
    alignItems: 'center',
    paddingVertical: 48,
  },
  emptyText: {
    fontSize: 18,
    fontWeight: '600',
    marginBottom: 4,
  },
  emptySubtext: {
    fontSize: 14,
  },
  completedSection: {
    marginTop: 16,
    paddingBottom: 24,
  },
  completedHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingHorizontal: 4,
    paddingVertical: 8,
  },
  completedTitle: {
    fontSize: 14,
    fontWeight: '600',
  },
  completedToggle: {
    fontSize: 14,
    fontWeight: '500',
  },
  completedList: {
    paddingTop: 8,
  },
  selectionBar: {
    position: 'absolute',
    left: 16,
    right: 16,
    bottom: 84,
    borderRadius: 20,
    borderWidth: 1,
    paddingHorizontal: 16,
    paddingVertical: 12,
    gap: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.15,
    shadowRadius: 12,
    elevation: 8,
  },
  selectionCancel: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 6,
    alignSelf: 'flex-start',
  },
  selectionCancelText: {
    fontSize: 14,
    fontWeight: '500',
  },
  selectionCount: {
    fontSize: 15,
    fontWeight: '700',
    textAlign: 'center',
  },
  selectionActions: {
    flexDirection: 'row',
    gap: 8,
  },
  selectionSecondRow: {
    flexDirection: 'row',
    gap: 8,
  },
  selectionButton: {
    flex: 1,
    paddingVertical: 10,
    borderRadius: 12,
    alignItems: 'center',
  },
  selectionButtonText: {
    color: '#FFFFFF',
    fontSize: 14,
    fontWeight: '600',
  },
});
