import React, { useEffect, useMemo, useRef, useState } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import WheelPickerExpo from 'react-native-wheel-picker-expo';
import dayjs from 'dayjs';
import { FloatingSelectionCard } from '@/components/ui/FloatingSelectionCard';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';

type FastingStartPickerModalProps = {
  visible: boolean;
  onClose: () => void;
  initialDate?: Date | null;
  recommendedDate?: Date | null;
  onConfirm: (date: Date) => void;
};

type DayOption = {
  label: string;
  offset: number;
};

const buildDayOptions = (now: dayjs.Dayjs): DayOption[] => ([
  { offset: -1, label: '昨天' },
  { offset: 0, label: '今天' },
  { offset: 1, label: '明天' },
].map((item) => ({
  ...item,
  label: item.offset === -1
    ? '昨天'
    : item.offset === 0
      ? '今天'
      : '明天',
})));

const HOURS = Array.from({ length: 24 }, (_, i) => i);
const MINUTES = Array.from({ length: 12 }, (_, i) => i * 5);

export function FastingStartPickerModal({
  visible,
  onClose,
  initialDate,
  recommendedDate,
  onConfirm,
}: FastingStartPickerModalProps) {
  const theme = useColorScheme() ?? 'light';
  const colors = Colors[theme];
  const now = useMemo(() => dayjs(), []);
  const dayOptions = useMemo(() => buildDayOptions(now), [now]);

  const deriveInitialIndexes = (source?: Date | null) => {
    const seed = source ? dayjs(source) : now;
    const dayDiff = seed.startOf('day').diff(now.startOf('day'), 'day');
    const dayIndex = dayOptions.findIndex((option) => option.offset === dayDiff);
    const hourIndex = HOURS.findIndex((hour) => hour === seed.hour());
    const snappedMinute = seed.minute() - (seed.minute() % 5);
    const minuteIndex = MINUTES.findIndex((minute) => minute === snappedMinute);

    return {
      dayIndex: dayIndex === -1 ? 1 : dayIndex,
      hourIndex: hourIndex === -1 ? now.hour() : hourIndex,
      minuteIndex:
        minuteIndex === -1
          ? Math.max(0, Math.min(MINUTES.length - 1, Math.floor(seed.minute() / 5)))
          : minuteIndex,
    };
  };

  const defaultBaseRef = useRef(new Date());

  const baseDate = useMemo(
    () => initialDate ?? recommendedDate ?? defaultBaseRef.current,
    [initialDate, recommendedDate]
  );

  const baseTimestamp = baseDate.getTime();

  const [{ dayIndex, hourIndex, minuteIndex }, setIndexes] = useState(() =>
    deriveInitialIndexes(baseDate)
  );
  const [pickerKey, setPickerKey] = useState(0);
  const lastAppliedTimestamp = useRef<number | null>(null);
  const wasVisibleRef = useRef(false);

  useEffect(() => {
    if (!visible) {
      wasVisibleRef.current = false;
      return;
    }

    const shouldReset =
      !wasVisibleRef.current ||
      lastAppliedTimestamp.current !== baseTimestamp;

    if (shouldReset) {
      const nextIndexes = deriveInitialIndexes(baseDate);
      setIndexes(nextIndexes);
      setPickerKey((prev) => prev + 1);
      lastAppliedTimestamp.current = baseTimestamp;
    }

    wasVisibleRef.current = true;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [visible, baseTimestamp]);

  const handleConfirm = () => {
    const selectedDay = dayOptions[dayIndex] ?? dayOptions[1];
    const base = now.startOf('day').add(selectedDay?.offset ?? 0, 'day');
    const hour = HOURS[hourIndex] ?? now.hour();
    const minute = MINUTES[minuteIndex] ?? 0;
    const result = base.hour(hour).minute(minute).second(0).millisecond(0);
    onConfirm(result.toDate());
    onClose();
  };

  const handleUseRecommended = () => {
    if (!recommendedDate) return;
    setIndexes(deriveInitialIndexes(recommendedDate));
    setPickerKey((prev) => prev + 1);
    lastAppliedTimestamp.current = recommendedDate.getTime();
  };

  const pickerIndicatorStyle = useMemo(
    () => ({
      backgroundColor: `${colors.primary}12`,
      borderRadius: 12,
    }),
    [colors.primary]
  );

  const textStyle = {
    fontSize: 18,
    fontWeight: '600' as const,
    color: '#2E3142',
  };

  return (
    <FloatingSelectionCard
      visible={visible}
      onClose={onClose}
      title="断食开始时间"
    >
      <View style={styles.pickerRow}>
        <WheelPickerExpo
          key={`day-${pickerKey}`}
          height={180}
          width={110}
          initialSelectedIndex={dayIndex}
          items={dayOptions.map((item) => ({ label: item.label, value: item.offset }))}
          onChange={({ index }) => setIndexes((prev) => ({ ...prev, dayIndex: index }))}
          backgroundColor="transparent"
          itemTextStyle={textStyle}
          selectedIndicatorStyle={pickerIndicatorStyle}
          haptics
        />
        <WheelPickerExpo
          key={`hour-${pickerKey}`}
          height={180}
          width={110}
          initialSelectedIndex={hourIndex}
          items={HOURS.map((hour) => ({ label: hour.toString().padStart(2, '0'), value: hour }))}
          onChange={({ index }) => setIndexes((prev) => ({ ...prev, hourIndex: index }))}
          backgroundColor="transparent"
          itemTextStyle={textStyle}
          selectedIndicatorStyle={pickerIndicatorStyle}
          haptics
        />
        <WheelPickerExpo
          key={`minute-${pickerKey}`}
          height={180}
          width={110}
          initialSelectedIndex={minuteIndex}
          items={MINUTES.map((minute) => ({
            label: minute.toString().padStart(2, '0'),
            value: minute,
          }))}
          onChange={({ index }) => setIndexes((prev) => ({ ...prev, minuteIndex: index }))}
          backgroundColor="transparent"
          itemTextStyle={textStyle}
          selectedIndicatorStyle={pickerIndicatorStyle}
          haptics
        />
      </View>

      <View style={styles.footerRow}>
        <TouchableOpacity
          style={[styles.recommendButton, { borderColor: colors.primary }]}
          onPress={handleUseRecommended}
          activeOpacity={0.85}
        >
          <Text style={[styles.recommendButtonText, { color: colors.primary }]}>使用推荐时间</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={[styles.confirmButton, { backgroundColor: colors.primary }]}
          onPress={handleConfirm}
          activeOpacity={0.9}
        >
          <Text style={styles.confirmButtonText}>确定</Text>
        </TouchableOpacity>
      </View>
    </FloatingSelectionCard>
  );
}

const styles = StyleSheet.create({
  pickerRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    width: '100%',
    marginBottom: 24,
  },
  footerRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    width: '100%',
  },
  recommendButton: {
    flex: 1,
    borderWidth: 1.2,
    borderRadius: 24,
    paddingVertical: 12,
    marginRight: 12,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'rgba(255,255,255,0.95)',
  },
  recommendButtonText: {
    fontSize: 14,
    fontWeight: '600',
  },
  confirmButton: {
    flex: 1,
    borderRadius: 24,
    paddingVertical: 12,
    alignItems: 'center',
    justifyContent: 'center',
  },
  confirmButtonText: {
    fontSize: 15,
    fontWeight: '700',
    color: '#fff',
  },
});
