import { Image } from 'expo-image'
import { StyleSheet, View } from 'react-native'
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withSpring,
} from 'react-native-reanimated'

const AnimatedImage = Animated.createAnimatedComponent(Image)

const PinchZoomImage = ({
  source,
  style,
  placeholder,
  contentFit,
}: {
  source: any
  style: any
  placeholder: any
  contentFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'
}) => {
  const scale = useSharedValue(1)
  const savedScale = useSharedValue(1)
  const translateX = useSharedValue(0)
  const translateY = useSharedValue(0)
  const originX = useSharedValue(0)
  const originY = useSharedValue(0)

  const pinchGesture = Gesture.Pinch()
    .onUpdate((event) => {
      const pinchScale = event.scale
      const nextScale = savedScale.value * pinchScale
      const touchX = event.focalX
      const touchY = event.focalY

      if (scale.value === savedScale.value) {
        originX.value = touchX
        originY.value = touchY
      }

      const focalDeltaX = (touchX - originX.value) * (pinchScale - 1)
      const focalDeltaY = (touchY - originY.value) * (pinchScale - 1)

      scale.value = nextScale
      translateX.value = focalDeltaX
      translateY.value = focalDeltaY
    })
    .onEnd(() => {
      savedScale.value = 1
      scale.value = withSpring(1)
      translateX.value = withSpring(0)
      translateY.value = withSpring(0)
    })

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

  return (
    <GestureDetector gesture={pinchGesture}>
      <Animated.View collapsable={false} style={styles.container}>
        <AnimatedImage
          source={source}
          style={[style, animatedStyle]}
          placeholder={placeholder}
          contentFit={contentFit}
          cachePolicy="memory"
          priority="high"
        />
      </Animated.View>
    </GestureDetector>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
})

const ZoomableImage = ({
  source,
  style,
  placeholder,
  contentFit,
}: {
  source: any
  style: any
  placeholder: any
  contentFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'
}) => {
  return (
    <View style={{ flex: 1 }}>
      <PinchZoomImage
        source={source}
        style={style}
        placeholder={placeholder}
        contentFit={contentFit}
      />
    </View>
  )
}

export default ZoomableImage
