import React, { useCallback, useEffect, useRef, useState } from 'react';
import {
  View,
  Text,
  StyleSheet,
  Modal,
  TouchableOpacity,
  FlatList,
  NativeScrollEvent,
  NativeSyntheticEvent,
  ListRenderItemInfo,
  LayoutChangeEvent,
} from 'react-native';
import { useSettings } from '@/theme';

const ITEM_HEIGHT = 44;
const VISIBLE_ITEMS = 5;
const MAX_COLUMN_WIDTH = 88;
const MIN_COLUMN_WIDTH = 64;
const HOURS = Array.from({ length: 24 }, (_, i) => i);
const MINUTES = Array.from({ length: 60 }, (_, i) => i);

interface WheelTimePickerProps {
  visible: boolean;
  title: string;
  initialTime?: string;
  onConfirm: (time: string) => void;
  onDismiss: () => void;
}

function parseTime(value?: string): { hours: number; minutes: number } {
  if (value) {
    const [h, m] = value.split(':').map(Number);
    if (!Number.isNaN(h) && !Number.isNaN(m)) {
      return { hours: ((h % 24) + 24) % 24, minutes: ((m % 60) + 60) % 60 };
    }
  }
  const now = new Date();
  return { hours: now.getHours(), minutes: now.getMinutes() };
}

function formatTime12(hours: number, minutes: number): string {
  const period = hours >= 12 ? 'PM' : 'AM';
  const h = hours % 12 === 0 ? 12 : hours % 12;
  return `${h}:${String(minutes).padStart(2, '0')} ${period}`;
}

interface WheelRowProps {
  label: string;
  selected: boolean;
  accent: string;
  textMuted: string;
  onPress: () => void;
}

const WheelRow = React.memo(function WheelRow({ label, selected, accent, textMuted, onPress }: WheelRowProps) {
  return (
    <TouchableOpacity
      style={[styles.row, selected && styles.rowSelected]}
      onPress={onPress}
      activeOpacity={0.6}
    >
      <Text
        style={[
          styles.rowText,
          { color: selected ? accent : textMuted },
          selected && styles.rowTextSelected,
        ]}
      >
        {label}
      </Text>
    </TouchableOpacity>
  );
});

interface WheelColumnProps {
  data: number[];
  initialIndex: number;
  selectedIndex: number;
  width: number;
  accent: string;
  textMuted: string;
  onIndexChange: (index: number) => void;
}

function WheelColumn({
  data,
  initialIndex,
  selectedIndex,
  width,
  accent,
  textMuted,
  onIndexChange,
}: WheelColumnProps) {
  const listRef = useRef<FlatList<number>>(null);
  const indexRef = useRef(initialIndex);

  useEffect(() => {
    listRef.current?.scrollToOffset({ offset: initialIndex * ITEM_HEIGHT - (ITEM_HEIGHT * VISIBLE_ITEMS - ITEM_HEIGHT) / 2, animated: false });
    indexRef.current = initialIndex;
  }, [initialIndex]);

  const selectIndex = useCallback(
    (index: number) => {
      const clamped = Math.min(Math.max(index, 0), data.length - 1);
      indexRef.current = clamped;
      onIndexChange(clamped);
      listRef.current?.scrollToOffset({ offset: clamped * ITEM_HEIGHT - (ITEM_HEIGHT * VISIBLE_ITEMS - ITEM_HEIGHT) / 2, animated: true });
    },
    [data.length, onIndexChange]
  );

  const renderItem = useCallback(
    ({ item, index }: ListRenderItemInfo<number>) => (
      <WheelRow
        label={String(item).padStart(2, '0')}
        selected={index === selectedIndex}
        accent={accent}
        textMuted={textMuted}
        onPress={() => selectIndex(index)}
      />
    ),
    [selectedIndex, accent, textMuted, selectIndex]
  );

  const handleScroll = useCallback(
    (event: NativeSyntheticEvent<NativeScrollEvent>) => {
      const offset = event.nativeEvent.contentOffset.y;
      const index = Math.round((offset + (ITEM_HEIGHT * VISIBLE_ITEMS - ITEM_HEIGHT) / 2) / ITEM_HEIGHT);
      const clamped = Math.min(Math.max(index, 0), data.length - 1);
      if (clamped !== indexRef.current) {
        indexRef.current = clamped;
        onIndexChange(clamped);
      }
    },
    [data.length, onIndexChange]
  );

  const handleScrollEnd = useCallback(() => {
    // Let FlatList's native snap handle the alignment
    // Just update the indexRef from the scroll position
    const current = listRef.current;
    if (!current) return;
    // The native snap will handle positioning, we just sync the index
  }, []);

  return (
      <FlatList
        ref={listRef}
        data={data}
        keyExtractor={(item) => String(item)}
        renderItem={renderItem}
        getItemLayout={(_data, index) => ({
          length: ITEM_HEIGHT,
          offset: ITEM_HEIGHT * index,
          index,
        })}
        initialScrollIndex={initialIndex}
        snapToOffsets={data.map((_, i) => i * ITEM_HEIGHT)}
        decelerationRate="normal"
        showsVerticalScrollIndicator={false}
        onScroll={handleScroll}
        onScrollEndDrag={handleScrollEnd}
        onMomentumScrollEnd={handleScrollEnd}
        scrollEventThrottle={16}
        style={[styles.column, { width }]}
        contentContainerStyle={{ paddingBottom: (VISIBLE_ITEMS - 1) * ITEM_HEIGHT, alignItems: 'stretch' }}
        snapToAlignment="center"
        snapToInterval={ITEM_HEIGHT}
      />
  );
}

export function WheelTimePicker({
  visible,
  title,
  initialTime,
  onConfirm,
  onDismiss,
}: WheelTimePickerProps) {
  const { theme } = useSettings();
  const initial = parseTime(initialTime);
  const [hourIndex, setHourIndex] = useState(initial.hours);
  const [minuteIndex, setMinuteIndex] = useState(initial.minutes);
  const [prevVisible, setPrevVisible] = useState(visible);
  const [wheelWidth, setWheelWidth] = useState(0);
  const [columnWidth, setColumnWidth] = useState(MAX_COLUMN_WIDTH);

  if (visible !== prevVisible) {
    setPrevVisible(visible);
    if (visible) {
      setHourIndex(initial.hours);
      setMinuteIndex(initial.minutes);
    }
  }

  const onWheelLayout = (event: LayoutChangeEvent) => {
    const width = event.nativeEvent.layout.width;
    if (Math.abs(width - wheelWidth) < 1) return;
    setWheelWidth(width);
    const available = Math.max(0, width - 24);
    setColumnWidth(Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, available / 2)));
  };

  return (
    <Modal visible={visible} transparent animationType="fade" onRequestClose={onDismiss}>
      <View style={[styles.overlay, { backgroundColor: theme.overlay }]}>
        <View style={[styles.sheet, { backgroundColor: theme.sheetBg }]}>
          <View style={styles.header}>
            <TouchableOpacity onPress={onDismiss} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}>
              <Text style={[styles.headerAction, { color: theme.textMuted }]}>Cancel</Text>
            </TouchableOpacity>
            <View style={styles.headerCenter}>
              <Text style={[styles.title, { color: theme.text }]}>{title}</Text>
              <Text style={[styles.preview, { color: theme.accentStrong }]}>
                {formatTime12(hourIndex, minuteIndex)}
              </Text>
            </View>
            <TouchableOpacity
              onPress={() => onConfirm(`${String(hourIndex).padStart(2, '0')}:${String(minuteIndex).padStart(2, '0')}`)}
              hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
            >
              <Text style={[styles.headerAction, styles.doneText, { color: theme.accentStrong }]}>Done</Text>
            </TouchableOpacity>
          </View>

          <View
            style={[styles.wheelArea, { height: ITEM_HEIGHT * VISIBLE_ITEMS }]}
            onLayout={onWheelLayout}
          >
            <WheelColumn
              data={HOURS}
              initialIndex={initial.hours}
              selectedIndex={hourIndex}
              width={columnWidth}
              accent={theme.accent}
              textMuted={theme.textMuted}
              onIndexChange={setHourIndex}
            />
            <View style={[styles.colonWrap, { width: 24, backgroundColor: theme.sheetBg }]}>
              <Text style={[styles.colon, { color: theme.accentStrong }]}>:</Text>
            </View>
            <WheelColumn
              data={MINUTES}
              initialIndex={initial.minutes}
              selectedIndex={minuteIndex}
              width={columnWidth}
              accent={theme.accent}
              textMuted={theme.textMuted}
              onIndexChange={setMinuteIndex}
            />
          </View>
        </View>
      </View>
    </Modal>
  );
}

const styles = StyleSheet.create({
  overlay: {
    flex: 1,
    justifyContent: 'flex-end',
  },
  sheet: {
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    paddingTop: 12,
    paddingBottom: 32,
    width: '100%',
    maxWidth: 420,
    alignSelf: 'center',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 20,
    paddingBottom: 8,
  },
  headerCenter: {
    alignItems: 'center',
  },
  headerAction: {
    fontSize: 15,
    fontWeight: '600',
    minWidth: 56,
  },
  doneText: {
    textAlign: 'right',
  },
  title: {
    fontSize: 16,
    fontWeight: '700',
  },
  preview: {
    fontSize: 13,
    fontWeight: '600',
    marginTop: 2,
  },
  wheelArea: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  column: {
    height: '100%',
  },
  colonWrap: {
    width: 24,
    alignItems: 'center',
    justifyContent: 'center',
    height: '100%',
  },
  row: {
    height: ITEM_HEIGHT,
    alignItems: 'center',
    justifyContent: 'center',
    width: '100%',
  },
  rowSelected: {
    backgroundColor: 'rgba(255,255,255,0.08)',
    borderRadius: 8,
  },
  rowText: {
    fontSize: 20,
    fontWeight: '500',
  },
  rowTextSelected: {
    fontSize: 22,
    fontWeight: '700',
  },
  colon: {
    fontSize: 24,
    fontWeight: '600',
  },
});
