import React, { useRef, useState, useEffect } from 'react';
import { View, StyleSheet, Platform, useWindowDimensions, PanResponder } from 'react-native';
import { Image } from 'expo-image';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import { FlatList } from 'react-native-gesture-handler';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  runOnJS,
} from 'react-native-reanimated';
import CustomVideoPlayer from './CustomVideoPlayer';

interface FullScreenSwiperProps {
  assets: any[];
  initialIndex: number;
  onClose: () => void;
  onIndexChange: (index: number) => void;
}

/* ─────────────────────────────────────────────────────────────
   ZoomableImage
   • Gesture.Pinch() — native multi-touch pinch-to-zoom
   • Gesture.Pan()   — single-finger swipe-down-to-close
   • Both run on the UI thread via reanimated worklets
   ───────────────────────────────────────────────────────────── */
function ZoomableImage({
  uri, thumbUri, width, height, onSwipeDown, onZoomChange,
}: {
  uri: string; thumbUri?: string; width: number;
  onSwipeDown: () => void; onZoomChange: (zooming: boolean) => void;
}) {
  const scale = useSharedValue(1);
  const savedScale = useSharedValue(1);
  const translateY = useSharedValue(0);

  const pinchGesture = Gesture.Pinch()
    .onStart(() => {
      'worklet';
      runOnJS(onZoomChange)(true);
    })
    .onUpdate((e) => {
      'worklet';
      scale.value = Math.max(0.5, Math.min(5, savedScale.value * e.scale));
    })
    .onEnd(() => {
      'worklet';
      runOnJS(onZoomChange)(false);
      if (scale.value < 1.15) {
        scale.value = withSpring(1, { damping: 15, stiffness: 150 });
        savedScale.value = 1;
      } else {
        savedScale.value = Math.min(5, scale.value);
      }
    });

  const panGesture = Gesture.Pan()
    .minPointers(1)
    .maxPointers(1)
    .activeOffsetY(20)
    .failOffsetX([-15, 15])
    .onStart(() => {
      'worklet';
      runOnJS(onZoomChange)(true);
    })
    .onUpdate((e) => {
      'worklet';
      translateY.value = e.translationY;
    })
    .onEnd((e) => {
      'worklet';
      runOnJS(onZoomChange)(false);
      if (e.translationY > 100) {
        runOnJS(onSwipeDown)();
      } else {
        translateY.value = withSpring(0, { damping: 15, stiffness: 150 });
      }
    });

  const composedGesture = Gesture.Simultaneous(pinchGesture, panGesture);

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

  return (
    <GestureDetector gesture={composedGesture}>
      <Animated.View
        style={[
          { width, height: '100%', justifyContent: 'center', alignItems: 'center' },
          animatedStyle,
        ]}
      >
        <Image
          source={{ uri }}
          placeholder={thumbUri ? { uri: thumbUri } : undefined}
          style={{ width: '100%', height: '100%' }}
          contentFit="contain"
          cachePolicy="memory-disk"
          transition={200}
          backgroundColor="transparent"
          allowDownscaling={false}
        />
      </Animated.View>
    </GestureDetector>
  );
}

/* ─────────────────────────────────────────────────────────────
   FullScreenSwiper
   Uses RNGH's FlatList so gesture handlers inside items
   properly negotiate with the scroll gesture on Android.
   ───────────────────────────────────────────────────────────── */
export default function FullScreenSwiper({
  assets, initialIndex, onClose, onIndexChange,
}: FullScreenSwiperProps) {
  const { width } = useWindowDimensions();
  const [activeIndex, setActiveIndex] = useState(initialIndex);
  const [scrollEnabled, setScrollEnabled] = useState(true);

  const onIndexChangeRef = useRef(onIndexChange);
  useEffect(() => { onIndexChangeRef.current = onIndexChange; }, [onIndexChange]);

  const onViewableItemsChanged = useRef(({ viewableItems }: any) => {
    if (viewableItems.length > 0) {
      const idx = viewableItems[0].index;
      setActiveIndex(idx);
      onIndexChangeRef.current(idx);
    }
  }).current;
  const viewabilityConfig = useRef({ itemVisiblePercentThreshold: 50 }).current;

  const renderItem = ({ item, index }: { item: any; index: number }) => {
    const isVideo =
      item.mediaType === 'video' ||
      item.filename?.toLowerCase().match(/\.(mp4|mov|avi|webm)$/i);
    const isActive = index === activeIndex;

    if (isVideo) {
      return (
        <View style={{ width, height: '100%', justifyContent: 'center', backgroundColor: '#000' }}>
          <CustomVideoPlayer
            uri={item.uri}
            shouldPlay={isActive}
            onScrubStart={() => setScrollEnabled(false)}
            onScrubEnd={() => setScrollEnabled(true)}
          />
        </View>
      );
    }

    return (
      <ZoomableImage
        uri={item.uri}
        thumbUri={item.cloudThumbUri}
        width={width}
        onSwipeDown={onClose}
        onZoomChange={(zooming) => setScrollEnabled(!zooming)}
      />
    );
  };

  return (
    <View style={styles.container}>
      <FlatList
        key={`swiper-${width}`}
        data={assets}
        keyExtractor={(item) => item.id}
        renderItem={renderItem}
        horizontal
        pagingEnabled
        scrollEnabled={scrollEnabled}
        showsHorizontalScrollIndicator={false}
        initialScrollIndex={activeIndex}
        getItemLayout={(_, index) => ({
          length: width,
          offset: width * index,
          index,
        })}
        onViewableItemsChanged={onViewableItemsChanged}
        viewabilityConfig={viewabilityConfig}
        windowSize={3}
        maxToRenderPerBatch={3}
        removeClippedSubviews={Platform.OS === 'android'}
        extraData={activeIndex}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000',
  },
});
