import React, { useMemo, useRef, useState, useCallback } from 'react';
import { View, Text, StyleSheet, SafeAreaView, ScrollView, TouchableOpacity, Animated, Dimensions, BackHandler, KeyboardAvoidingView } from 'react-native';
import { useRouter, useFocusEffect } from 'expo-router';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import { Header } from '@/components/Header';
import { useTasksByDate, useTasksInMonth } from '@/hooks/useTasks';
import { useSubtasks } from '@/hooks/useSubtasks';
import { useTaskModals } from '@/hooks/useTaskModals';
import { useSettings } from '@/theme';
import { useCategories } from '@/hooks/useDatabase';
import { toggleTaskComplete } from '@/utils/taskActions';
import { QuickAddBar } from '@/components/QuickAddBar';
import { OptionPickerModal } from '@/components/OptionPickerModal';
import Task from '@/models/Task';
import { format, addMonths, addDays, startOfMonth, isSameDay, isSameMonth, isToday } from 'date-fns';
import Svg, { Path, Circle } from 'react-native-svg';
import { desaturate } from '@/theme';
import type { ThemeColors } from '@/theme';

const WIDTH = Dimensions.get('window').width;
const GERMAN_WEEKDAYS = ['mo', 'di', 'mi', 'do', 'fr', 'sa', 'so'];
const MONTH_NAMES = [
  'January', 'February', 'March', 'April', 'May', 'June',
  'July', 'August', 'September', 'October', 'November', 'December',
];

export default function CalendarScreen() {
  const router = useRouter();
  const { theme } = useSettings();
  const categories = useCategories();
  const { modals, openTaskEdit } = useTaskModals();

  const [visibleMonth, setVisibleMonth] = useState(() => new Date());
  const [selectedDate, setSelectedDate] = useState(() => new Date());
  const [monthPickerVisible, setMonthPickerVisible] = useState(false);
  const [yearPickerVisible, setYearPickerVisible] = useState(false);
  const { map: subtasksByTask, refresh: refreshSubtasks } = useSubtasks();

  const visibleMonthRef = useRef(visibleMonth);
  visibleMonthRef.current = visibleMonth;
  const selectedDateRef = useRef(selectedDate);
  selectedDateRef.current = selectedDate;

  const { tasks: selectedDayTasks, refresh: refreshDayTasks } = useTasksByDate(selectedDate);
  const monthTasks = useTasksInMonth(visibleMonth);
  const refreshMonthTasks = monthTasks.refresh;

  useFocusEffect(
    useCallback(() => {
      const sub = BackHandler.addEventListener('hardwareBackPress', () => true);
      refreshDayTasks();
      refreshMonthTasks();
      refreshSubtasks();
      return () => sub.remove();
    }, [refreshDayTasks, refreshMonthTasks, refreshSubtasks])
  );

  const translateX = useRef(new Animated.Value(0)).current;
  const animatingRef = useRef(false);
  const gridWidthRef = useRef<number>(WIDTH);

  const weeks = useMemo(() => {
    const first = startOfMonth(visibleMonth);
    const offset = (first.getDay() + 6) % 7; // week starts Monday
    const gridStart = addDays(first, -offset);
    const cells = Array.from({ length: 42 }, (_, i) => addDays(gridStart, i));
    const rows: Date[][] = [];
    for (let i = 0; i < 42; i += 7) rows.push(cells.slice(i, i + 7));
    return rows;
  }, [visibleMonth]);

  const transitionTo = useCallback(
    (dir: 1 | -1, animate = true) => {
      if (animatingRef.current) return;
      const next = addMonths(visibleMonthRef.current, dir);
      if (!isSameMonth(selectedDateRef.current, next)) {
        setSelectedDate(startOfMonth(next));
      }
      if (!animate) {
        setVisibleMonth(next);
        translateX.setValue(0);
        return;
      }
      animatingRef.current = true;
      const w = gridWidthRef.current || WIDTH;
      const target = dir === 1 ? -w : w;
      Animated.timing(translateX, { toValue: target, duration: 220, useNativeDriver: false }).start(() => {
        setVisibleMonth(next);
        translateX.setValue(-target);
        Animated.timing(translateX, { toValue: 0, duration: 180, useNativeDriver: false }).start(() => {
          animatingRef.current = false;
        });
      });
    },
    [translateX]
  );

  const handleDayPress = useCallback(
    (day: Date) => {
      setSelectedDate(day);
      if (!isSameMonth(day, visibleMonthRef.current)) {
        transitionTo(day > visibleMonthRef.current ? 1 : -1, true);
      } else {
        router.push({ pathname: '/day-view', params: { date: day.toISOString() } });
      }
    },
    [router, transitionTo]
  );

  const pan = useMemo(
    () =>
      Gesture.Pan()
        .activeOffsetX([-16, 16])
        .minDistance(6)
        .runOnJS(true)
        .onUpdate((e) => {
          if (!animatingRef.current) translateX.setValue(e.translationX);
        })
        .onEnd((e) => {
          if (animatingRef.current) return;
          const w = gridWidthRef.current || WIDTH;
          const dx = e.translationX;
          if (dx <= -w / 4) {
            translateX.stopAnimation();
            transitionTo(1, false);
          } else if (dx >= w / 4) {
            translateX.stopAnimation();
            transitionTo(-1, false);
          } else {
            Animated.spring(translateX, { toValue: 0, useNativeDriver: false }).start();
          }
        }),
    [translateX, transitionTo]
  );

  const handleSelectMonth = useCallback((value: string | string[]) => {
    const monthIndex = parseInt(Array.isArray(value) ? value[0] : value, 10);
    setVisibleMonth(new Date(visibleMonthRef.current.getFullYear(), monthIndex, 1));
  }, []);

  const handleSelectYear = useCallback((value: string | string[]) => {
    const year = parseInt(Array.isArray(value) ? value[0] : value, 10);
    setVisibleMonth(new Date(year, visibleMonthRef.current.getMonth(), 1));
  }, []);

  const currentYear = new Date().getFullYear();
  const monthOptions = MONTH_NAMES.map((label, i) => ({ value: String(i), label }));
  const yearOptions = useMemo(() => {
    const options: { value: string; label: string }[] = [];
    for (let y = currentYear - 20; y <= currentYear + 10; y++) options.push({ value: String(y), label: String(y) });
    return options;
  }, [currentYear]);

  const handleToggleComplete = useCallback(async (taskId: string) => {
    await toggleTaskComplete(taskId);
    refreshDayTasks();
    refreshMonthTasks();
    refreshSubtasks();
  }, [refreshDayTasks, refreshMonthTasks, refreshSubtasks]);

  return (
    <SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
      <Header title="Calendar" showLogo={false} />

      <KeyboardAvoidingView style={styles.kbAvoid} behavior="padding">
      <ScrollView style={styles.scrollBody} showsVerticalScrollIndicator={false} contentContainerStyle={styles.scrollContent}>
        <GestureDetector gesture={pan}>
          <Animated.View
            onLayout={(e) => {
              gridWidthRef.current = e.nativeEvent.layout.width;
            }}
            style={[styles.calendarArea, { transform: [{ translateX }] }]}
          >
              <View style={styles.monthRow}>
                <TouchableOpacity
                  onPress={() => transitionTo(-1)}
                  style={[styles.monthNav, { borderColor: theme.borderStrong, backgroundColor: theme.card }]}
                  activeOpacity={0.7}
                >
                  <Svg width={20} height={20} viewBox="0 0 24 24">
                    <Path d="M15 18l-6-6 6-6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
                  </Svg>
                </TouchableOpacity>

                <View style={styles.monthSelectorGroup}>
                  <TouchableOpacity onPress={() => setMonthPickerVisible(true)} activeOpacity={0.7} style={styles.monthButton}>
                    <Text style={[styles.monthLabel, { color: theme.text }]}>{format(visibleMonth, 'MMMM')}</Text>
                    <Svg width={14} height={14} viewBox="0 0 24 24">
                      <Path d="M6 9l6 6 6-6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
                    </Svg>
                  </TouchableOpacity>
                </View>

                <TouchableOpacity onPress={() => setYearPickerVisible(true)} activeOpacity={0.7} style={styles.yearButton}>
                  <Text style={[styles.yearLabel, { color: theme.textMuted }]}>{format(visibleMonth, 'yyyy')}</Text>
                </TouchableOpacity>

                <TouchableOpacity
                  onPress={() => transitionTo(1)}
                  style={[styles.monthNav, { borderColor: theme.borderStrong, backgroundColor: theme.card }]}
                  activeOpacity={0.7}
                >
                  <Svg width={20} height={20} viewBox="0 0 24 24">
                    <Path d="M9 6l6 6-6 6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
                  </Svg>
                </TouchableOpacity>
              </View>

              <View style={styles.weekdayRow}>
                {GERMAN_WEEKDAYS.map((day, i) => (
                  <Text key={day + i} style={[styles.weekday, { color: theme.textMuted }]}>
                    {day}
                  </Text>
                ))}
              </View>

              {weeks.map((week, wi) => (
                <View key={wi} style={styles.weekRow}>
                  {week.map((day) => (
                    <DayCell
                      key={day.toISOString()}
                      day={day}
                      label={cellTitle(byDayOf(monthTasks.byDay, day))}
                      dotColor={cellColor(byDayOf(monthTasks.byDay, day), categories)}
                      selected={isSameDay(day, selectedDate)}
                      today={isToday(day)}
                      inMonth={isSameMonth(day, visibleMonth)}
                      theme={theme}
                      onPress={handleDayPress}
                    />
                  ))}
                </View>
              ))}
            </Animated.View>
        </GestureDetector>

        <View style={styles.panelHeader}>
              <Text style={[styles.panelDate, { color: theme.text }]}>{format(selectedDate, 'EEEE, MMMM d')}</Text>
              {selectedDayTasks.length > 0 && (
                <Text style={[styles.panelCount, { color: theme.textFaint }]}>
                  {selectedDayTasks.length} event{selectedDayTasks.length === 1 ? '' : 's'}
                </Text>
              )}
            </View>

            {selectedDayTasks.length === 0 ? (
              <View style={styles.emptyState}>
                <Text style={[styles.emptyText, { color: theme.textSecondary }]}>No events on this day</Text>
                <Text style={[styles.emptySubtext, { color: theme.textMuted }]}>Tap a date or use the bar below</Text>
              </View>
            ) : (
              selectedDayTasks.map((task) => (
                <View key={task.id} style={[styles.eventCard, { backgroundColor: theme.card, borderColor: theme.border }]}>
                  <View style={styles.eventRow}>
                    <TouchableOpacity
                      style={styles.checkCircle}
                      onPress={() => handleToggleComplete(task.id)}
                      activeOpacity={0.7}
                    >
                      <Svg width={30} height={30} viewBox="0 0 24 24">
                        {task.completed ? (
                          <>
                            <Circle cx={12} cy={12} r={10} fill={theme.accent} />
                            <Path d="M7 12l3 3 7-7" stroke="#FFFFFF" strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
                          </>
                        ) : (
                          <Circle cx={12} cy={12} r={10} stroke={theme.textSecondary} strokeWidth={2.5} fill="none" />
                        )}
                      </Svg>
                    </TouchableOpacity>

                    <TouchableOpacity
                      style={styles.eventTitleTouch}
                      onPress={() => router.push({ pathname: '/task-detail', params: { id: task.id } })}
                      activeOpacity={0.7}
                    >
                      <Text
                        style={[styles.eventTitle, { color: theme.text }, task.completed && styles.eventCompleted]}
                        numberOfLines={1}
                      >
                        {task.title}
                      </Text>
                    </TouchableOpacity>

                    <TouchableOpacity style={styles.menuButton} onPress={() => openTaskEdit(task.id)} activeOpacity={0.7} accessibilityRole="button" accessibilityLabel={`Edit ${task.title}`}>
                      <Svg width={20} height={20} viewBox="0 0 24 24">
                        <Path d="M9 6l6 6-6 6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
                      </Svg>
                    </TouchableOpacity>
                  </View>

                  {(subtasksByTask.get(task.id) ?? []).length > 0 && (
                    <View style={styles.bullets}>
                      {(subtasksByTask.get(task.id) ?? []).map((sub) => (
                        <View key={sub.id} style={styles.bulletRow}>
                          <Svg width={5} height={5} viewBox="0 0 6 6" style={styles.bulletDot as any}>
                            <Circle cx={3} cy={3} r={3} fill={theme.textMuted} />
                          </Svg>
                          <Text
                            style={[styles.bulletText, { color: theme.textFaint }, sub.completed && styles.bulletCompleted]}
                            numberOfLines={1}
                          >
                            {sub.title}
                          </Text>
                        </View>
                      ))}
                    </View>
                  )}
                </View>
              ))
            )}
          </ScrollView>

      <QuickAddBar
        dueDate={selectedDate.getTime()}
        placeholder={`Add event for ${format(selectedDate, 'MMM d')}`}
      />
      </KeyboardAvoidingView>

      {modals(() => {})}

      <OptionPickerModal
        visible={monthPickerVisible}
        title="Select Month"
        options={monthOptions}
        selectedValue={String(visibleMonth.getMonth())}
        onSelect={handleSelectMonth}
        onClose={() => setMonthPickerVisible(false)}
      />
      <OptionPickerModal
        visible={yearPickerVisible}
        title="Select Year"
        options={yearOptions}
        selectedValue={String(visibleMonth.getFullYear())}
        onSelect={handleSelectYear}
        onClose={() => setYearPickerVisible(false)}
      />
    </SafeAreaView>
  );
}

function byDayOf(byDay: Record<number, Task[]>, day: Date): Task[] {
  return byDay[day.getDate()] ?? [];
}

function cellTitle(tasks: Task[]): string | null {
  if (tasks.length === 0) return null;
  if (tasks.length === 1) return tasks[0].title;
  return `${tasks[0].title} +${tasks.length - 1}`;
}

function cellColor(tasks: Task[], categories: { id: string; color: string }[]): string {
  if (tasks.length === 0) return '#8E8E8E';
  const cat = categories.find((c) => c.id === tasks[0].categoryId);
  return cat ? desaturate(cat.color, 0.3) : '#8E8E8E';
}

interface DayCellProps {
  day: Date;
  label: string | null;
  dotColor: string;
  selected: boolean;
  today: boolean;
  inMonth: boolean;
  theme: ThemeColors;
  onPress: (day: Date) => void;
}

const DayCell = React.memo(function DayCell({ day, label, dotColor, selected, today, inMonth, theme, onPress }: DayCellProps) {
  return (
    <TouchableOpacity
      style={[styles.dayCell, selected && { backgroundColor: theme.accentSoft, borderColor: theme.accentBorder }]}
      onPress={() => onPress(day)}
      activeOpacity={0.7}
    >
      <Text
        style={[
          styles.dayNumber,
          { color: theme.text },
          !inMonth && { color: theme.textMuted },
          today && !selected && { color: theme.accent },
          selected && styles.dayNumberSelected,
        ]}
      >
        {format(day, 'd')}
      </Text>
      {label ? (
        <View style={[styles.chip, { backgroundColor: selected ? 'rgba(0,0,0,0.22)' : dotColor }]}>
          <Text style={styles.chipText} numberOfLines={1}>
            {label}
          </Text>
        </View>
      ) : !inMonth ? (
        <View style={[styles.chipPlaceholder, { backgroundColor: theme.borderStrong }]} />
      ) : null}
    </TouchableOpacity>
  );
});

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  scrollContent: {
    paddingBottom: 16,
    flexGrow: 1,
  },
  scrollBody: {
    flex: 1,
  },
  kbAvoid: {
    flex: 1,
  },
  calendarArea: {
    paddingHorizontal: 12,
    paddingTop: 6,
    paddingBottom: 4,
  },
  monthRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 4,
    paddingBottom: 14,
  },
  monthNav: {
    width: 36,
    height: 36,
    borderRadius: 12,
    borderWidth: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  monthSelectorGroup: {
    alignItems: 'flex-start',
    flex: 1,
  },
  monthButton: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    gap: 6,
    paddingHorizontal: 10,
  },
  monthLabel: {
    fontSize: 22,
    fontWeight: '700',
  },
  yearButton: {
    marginTop: -2,
    paddingHorizontal: 6,
  },
  yearLabel: {
    fontSize: 17,
    fontWeight: '700',
  },
  weekdayRow: {
    flexDirection: 'row',
    marginBottom: 4,
    paddingHorizontal: 2,
  },
  weekday: {
    flex: 1,
    textAlign: 'center',
    fontSize: 11,
    fontWeight: '600',
    textTransform: 'uppercase',
  },
  weekRow: {
    flexDirection: 'row',
    gap: 6,
    marginBottom: 6,
  },
  dayCell: {
    flex: 1,
    height: 56,
    borderRadius: 12,
    borderWidth: 1,
    borderColor: 'transparent',
    paddingVertical: 4,
    alignItems: 'center',
  },
  dayNumber: {
    fontSize: 14,
    fontWeight: '600',
  },
  dayNumberSelected: {
    color: '#FFFFFF',
  },
  chip: {
    marginTop: 3,
    paddingHorizontal: 4,
    paddingVertical: 2,
    borderRadius: 5,
    maxWidth: '92%',
  },
  chipText: {
    color: '#FFFFFF',
    fontSize: 8,
    fontWeight: '600',
  },
  chipPlaceholder: {
    marginTop: 3,
    width: 6,
    height: 2,
    borderRadius: 1,
    opacity: 0.4,
  },
  panelHeader: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 18,
    paddingTop: 15,
    paddingBottom: 4,
  },
  panelDate: {
    fontSize: 16,
    fontWeight: '700',
  },
  panelCount: {
    fontSize: 13,
  },
  emptyState: {
    alignItems: 'center',
    paddingVertical: 36,
  },
  emptyText: {
    fontSize: 15,
    fontWeight: '600',
    marginBottom: 4,
  },
  emptySubtext: {
    fontSize: 13,
  },
  eventCard: {
    marginHorizontal: 16,
    marginTop: 6,
    borderRadius: 16,
    borderWidth: 1,
    paddingHorizontal: 14,
    paddingVertical: 12,
  },
  eventRow: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  checkCircle: {
    width: 30,
    marginRight: 12,
  },
  eventTitleTouch: {
    flex: 1,
  },
  eventTitle: {
    fontSize: 15,
    fontWeight: '500',
  },
  eventCompleted: {
    textDecorationLine: 'line-through',
    color: '#9E9E9E',
  },
  menuButton: {
    padding: 4,
    marginLeft: 6,
  },
  bullets: {
    marginTop: 8,
    paddingTop: 8,
    borderTopWidth: 1,
    borderTopColor: 'rgba(255,255,255,0.06)',
    gap: 6,
  },
  bulletRow: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  bulletDot: {
    marginLeft: 8,
  },
  bulletText: {
    flex: 1,
    fontSize: 13,
  },
  bulletCompleted: {
    textDecorationLine: 'line-through',
    color: '#6E6E6E',
  },
});