import React, { useMemo, useRef, useState, useImperativeHandle, forwardRef, useCallback, useEffect } from 'react';
import { View, Pressable, StyleSheet, Dimensions, TouchableWithoutFeedback } from 'react-native';
import Animated, { useSharedValue, useAnimatedRef, useAnimatedStyle, withTiming, withSpring, useAnimatedScrollHandler, scrollTo, interpolate, Extrapolation, runOnJS, runOnUI } from 'react-native-reanimated';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import CustomText from '@/components/common/CustomText.jsx';
import { wp, sp } from '@/utils/ui/screenUtils';
import { useAppStore } from '@/stores';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTranslation } from 'react-i18next';

const ITEM_HEIGHT = wp(48);
const VISIBLE_ITEMS = 5;
const SCREEN_HEIGHT = Dimensions.get('window').height;

const PickerItem = React.memo(({ index, scrollY, label }) => {
  const style = useAnimatedStyle(() => {
    const inputRange = [
      (index - 2) * ITEM_HEIGHT,
      (index - 1) * ITEM_HEIGHT,
      index * ITEM_HEIGHT,
      (index + 1) * ITEM_HEIGHT,
      (index + 2) * ITEM_HEIGHT,
    ];

    const scale = interpolate(
      scrollY.value,
      inputRange,
      [0.9, 0.95, 1.1, 0.95, 0.9],
      Extrapolation.CLAMP
    );

    const opacity = interpolate(
      scrollY.value,
      inputRange,
      [0.4, 0.6, 1, 0.6, 0.4],
      Extrapolation.CLAMP
    );

    return {
      transform: [{ scale }],
      opacity,
    };
  });

  return (
    <Animated.View style={[styles.itemContainer, style]}>
      <CustomText style={styles.itemText} numberOfLines={1}>{label}</CustomText>
    </Animated.View>
  );
});

const CustomSelect = forwardRef(({ title = '请选择', options = [], value, onChange, onCancel, keyExtractor }, ref) => {
  const insets = useSafeAreaInsets();
  const safeBottom = insets.bottom < 20 ? wp(20) : insets.bottom;
  const primaryColor = useAppStore((s) => s.primary);
  const { t } = useTranslation();
  const [isVisible, setIsVisible] = useState(false);
  const listRef = useAnimatedRef();

  const scrollY = useSharedValue(0);
  const active = useSharedValue(0);
  const sheetHeight = useMemo(() => {
    const headerHeight = wp(48);
    const footerHeight = wp(44);
    const gap = wp(20);
    const contentHeight = ITEM_HEIGHT * VISIBLE_ITEMS + headerHeight + footerHeight + gap + safeBottom + wp(10);
    return Math.min(SCREEN_HEIGHT * 0.8, contentHeight);
  }, [safeBottom]);
  const translateY = useSharedValue(sheetHeight);
  const context = useSharedValue({ y: 0 });

  const isVisibleRef = useRef(isVisible);
  useEffect(() => { isVisibleRef.current = isVisible; }, [isVisible]);

  const optionsRef = useRef(options);
  useEffect(() => { optionsRef.current = options; }, [options]);

  const valueRef = useRef(value);
  useEffect(() => { valueRef.current = value; }, [value]);

  const selectedValueRef = useRef(value);
  useEffect(() => { selectedValueRef.current = value; }, [value]);

  const initialIndex = useMemo(() => {
    const v = value;
    const idx = options.findIndex(o => (o?.value ?? o) === v);
    if (idx >= 0) return idx;
    return options.length ? Math.floor(options.length / 2) : 0;
  }, [options, value]);

  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (e) => { scrollY.value = e.contentOffset.y; },
  });

  const gesture = useMemo(() => Gesture.Pan()
    .onStart(() => { context.value = { y: translateY.value }; })
    .onUpdate((e) => { translateY.value = Math.max(0, context.value.y + e.translationY); })
    .onEnd((e) => {
      if (translateY.value > sheetHeight * 0.2 || e.velocityY > 500) {
        runOnJS(closeSheet)();
      } else {
        translateY.value = withSpring(0, { damping: 20, stiffness: 90 });
      }
    }), [sheetHeight, context, translateY]);

  const backdropStyle = useAnimatedStyle(() => ({
    opacity: active.value,
  }));

  const sheetStyle = useAnimatedStyle(() => ({
    transform: [{ translateY: translateY.value }],
  }));

  const present = useCallback(() => {
    if (!isVisibleRef.current) setIsVisible(true);
    active.value = withTiming(1, { duration: 250 });
    translateY.value = withSpring(0, { damping: 20, stiffness: 90, mass: 0.5 });

    const opts = optionsRef.current || [];
    const target = (valueRef.current ?? selectedValueRef.current);
    let idx = opts.findIndex(o => (o?.value ?? o) === target);
    if (idx < 0) idx = opts.length ? Math.floor(opts.length / 2) : 0;

    const nextOffset = idx * ITEM_HEIGHT;
    runOnUI((y) => {
      'worklet';
      scrollTo(listRef, 0, y, false);
      scrollY.value = y;
    })(nextOffset);

    if (selectedValueRef.current == null && valueRef.current == null) {
      const item = opts[idx];
      if (item !== undefined) selectedValueRef.current = (item?.value ?? item);
    }
  }, [scrollY, translateY, active, listRef]);

  const closeSheet = useCallback(() => {
    if (!isVisibleRef.current) return;
    active.value = withTiming(0, { duration: 200 });
    translateY.value = withTiming(sheetHeight, { duration: 250 }, (finished) => {
      if (finished) runOnJS(setIsVisible)(false);
    });
  }, [sheetHeight]);

  const dismiss = useCallback(() => { closeSheet(); }, [closeSheet]);
  useImperativeHandle(ref, () => ({ present, dismiss }));

  const handleCancel = useCallback(() => {
    selectedValueRef.current = valueRef.current;
    dismiss();
  }, [dismiss]);
  const handleConfirm = useCallback(() => {
    let idx = Math.round(scrollY.value / ITEM_HEIGHT);
    if (idx < 0) idx = 0;
    if (idx >= options.length) idx = options.length - 1;
    const item = options[idx];
    const v = item?.value ?? item;
    selectedValueRef.current = v;
    onChange && onChange(v);
    dismiss();
  }, [options, onChange, dismiss]);

  const renderItem = useCallback(({ item, index }) => {
    const label = item?.label ?? String(item);
    return <PickerItem index={index} scrollY={scrollY} label={label} />;
  }, [scrollY]);

  const getItemLayout = useCallback((_, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index }), []);

  const handleMomentumScrollEnd = useCallback((e) => {
    const y = e?.nativeEvent?.contentOffset?.y ?? 0;
    const idx = Math.round(y / ITEM_HEIGHT);
    const arr = optionsRef.current || [];
    if (idx >= 0 && idx < arr.length) {
      const item = arr[idx];
      selectedValueRef.current = (item?.value ?? item);
    }
  }, []);

  return (
    <View style={[StyleSheet.absoluteFill, { zIndex: isVisible ? 100 : -1 }]} pointerEvents={isVisible ? 'auto' : 'none'}>
      <TouchableWithoutFeedback onPress={closeSheet}>
        <Animated.View style={[styles.backdrop, backdropStyle]} />
      </TouchableWithoutFeedback>

      <Animated.View
        style={[
          styles.sheetContainer,
          { height: sheetHeight, bottom: 0 },
          sheetStyle,
        ]}
      >
        <View style={[styles.container, { paddingBottom: safeBottom + wp(10) }] }>
          <GestureDetector gesture={gesture}>
            <View style={styles.header}>
              <CustomText style={styles.headerTitle}>{title}</CustomText>
            </View>
          </GestureDetector>

          <View style={styles.pickerWrapper}>
            <View style={[styles.highlightBar, { backgroundColor: '#F0F0F0' }]} />
            <Animated.FlatList
              ref={listRef}
              data={options}
              renderItem={renderItem}
              keyExtractor={(item, index) => {
                if (keyExtractor) return keyExtractor(item, index);
                return String(item?.value ?? item ?? index);
              }}
              getItemLayout={getItemLayout}
              snapToInterval={ITEM_HEIGHT}
              decelerationRate="fast"
              showsVerticalScrollIndicator={false}
              removeClippedSubviews
              windowSize={5}
              initialNumToRender={VISIBLE_ITEMS + 2}
              maxToRenderPerBatch={VISIBLE_ITEMS + 4}
              updateCellsBatchingPeriod={16}
              contentContainerStyle={{ paddingVertical: ITEM_HEIGHT * ((VISIBLE_ITEMS - 1) / 2) }}
              onScroll={scrollHandler}
              scrollEventThrottle={16}
              initialScrollIndex={initialIndex}
              onMomentumScrollEnd={handleMomentumScrollEnd}
            />
          </View>

          <View style={styles.footer}>
            <Pressable
              style={({ pressed }) => [
                styles.btn,
                { backgroundColor: `${primaryColor}15` },
                pressed && { opacity: 0.7 },
              ]}
              onPress={() => { onCancel && onCancel(); handleCancel(); }}
            >
              <CustomText style={[styles.btnText, { color: primaryColor }]}>{t('buttons.cancel')}</CustomText>
            </Pressable>
            <Pressable
              style={({ pressed }) => [
                styles.btn,
                { backgroundColor: primaryColor },
                pressed && { opacity: 0.8 },
              ]}
              onPress={handleConfirm}
            >
              <CustomText style={[styles.btnText, { color: '#FFFFFF' }]}>{t('buttons.confirm')}</CustomText>
            </Pressable>
          </View>
        </View>
      </Animated.View>
    </View>
  );
});

export default CustomSelect;

const styles = StyleSheet.create({
  backdrop: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'rgba(0,0,0,0.4)',
  },
  sheetContainer: {
    position: 'absolute',
    left: 0,
    right: 0,
    backgroundColor: '#FFFFFF',
    borderTopLeftRadius: wp(16),
    borderTopRightRadius: wp(16),
    overflow: 'hidden',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: -2 },
    shadowOpacity: 0.08,
    shadowRadius: 4,
    elevation: 5,
  },
  container: { paddingHorizontal: wp(16), paddingTop: wp(10) },
  header: { alignItems: 'center', justifyContent: 'center', paddingBottom: wp(16) },
  headerTitle: { fontSize: sp(18), fontWeight: '600', color: '#333333' },
  pickerWrapper: { height: ITEM_HEIGHT * VISIBLE_ITEMS, position: 'relative', width: '100%' },
  highlightBar: {
      position: 'absolute',
      top: ITEM_HEIGHT * ((VISIBLE_ITEMS - 1) / 2),
      left: 0,
      right: 0,
      height: ITEM_HEIGHT,
      borderRadius: wp(8),
      zIndex: -1,
  },
  itemContainer: { height: ITEM_HEIGHT, justifyContent: 'center', alignItems: 'center' },
  itemText: { fontSize: sp(18), color: '#333333' },
  footer: { flexDirection: 'row', marginTop: wp(20), gap: wp(12) },
  btn: { flex: 1, height: wp(44), borderRadius: wp(22), justifyContent: 'center', alignItems: 'center' },
  btnText: { fontSize: sp(16), fontWeight: '600' },
});
