/**
 * 可滑动的消息气泡容器
 * 实现滑动回复手势功能 - 严格单向滑动，无抖动
 */

import React, { useRef, useCallback } from 'react';
import { View, StyleSheet, Animated, Platform } from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { PanGestureHandler, State } from 'react-native-gesture-handler';
import * as Haptics from 'expo-haptics';
import { useAppColors } from '../../../../theme';

const SWIPE_THRESHOLD = 30;
const MAX_SWIPE_DISTANCE = 50;

interface SwipeableMessageBubbleProps {
  children: React.ReactNode;
  isMe: boolean;
  onReply: () => void;
  enabled?: boolean;
}

export const SwipeableMessageBubble: React.FC<SwipeableMessageBubbleProps> = ({
  children,
  isMe,
  onReply,
  enabled = true,
}) => {
  const colors = useAppColors();
  const translateX = useRef(new Animated.Value(0)).current;
  const hasTriggeredRef = useRef(false);

  const onGestureEvent = Animated.event(
    [{ nativeEvent: { translationX: translateX } }],
    { useNativeDriver: true }
  );

  const onHandlerStateChange = useCallback((event: any) => {
    const { nativeEvent } = event;
    
    if (nativeEvent.state === State.END) {
      const translationX = nativeEvent.translationX;
      
      const shouldTrigger = isMe 
        ? translationX < -SWIPE_THRESHOLD
        : translationX > SWIPE_THRESHOLD;
      
      if (shouldTrigger && !hasTriggeredRef.current) {
        hasTriggeredRef.current = true;
        
        if (Platform.OS !== 'web') {
          Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
        }
        
        onReply();
        
        setTimeout(() => {
          hasTriggeredRef.current = false;
        }, 300);
      }
      
      translateX.setValue(0);
    }
  }, [isMe, onReply]);

  const iconOpacity = translateX.interpolate({
    inputRange: isMe 
      ? [-MAX_SWIPE_DISTANCE, -SWIPE_THRESHOLD, 0, 10] 
      : [-10, 0, SWIPE_THRESHOLD, MAX_SWIPE_DISTANCE],
    outputRange: isMe ? [1, 0.8, 0, 0] : [0, 0, 0.8, 1],
    extrapolate: 'clamp',
  });

  const clampedTranslateX = translateX.interpolate({
    inputRange: isMe 
      ? [-MAX_SWIPE_DISTANCE - 10, -MAX_SWIPE_DISTANCE, 0, 10] 
      : [-10, 0, MAX_SWIPE_DISTANCE, MAX_SWIPE_DISTANCE + 10],
    outputRange: isMe 
      ? [-MAX_SWIPE_DISTANCE, -MAX_SWIPE_DISTANCE, 0, 0] 
      : [0, 0, MAX_SWIPE_DISTANCE, MAX_SWIPE_DISTANCE],
    extrapolate: 'clamp',
  });

  const webTouchStartRef = useRef<{ x: number; time: number } | null>(null);
  const webTranslateXRef = useRef(new Animated.Value(0)).current;
  const webIconOpacity = webTranslateXRef.interpolate({
    inputRange: isMe 
      ? [-MAX_SWIPE_DISTANCE, -SWIPE_THRESHOLD, 0, 10] 
      : [-10, 0, SWIPE_THRESHOLD, MAX_SWIPE_DISTANCE],
    outputRange: isMe ? [1, 0.8, 0, 0] : [0, 0, 0.8, 1],
    extrapolate: 'clamp',
  });
  const webClampedTranslateX = webTranslateXRef.interpolate({
    inputRange: isMe 
      ? [-MAX_SWIPE_DISTANCE - 10, -MAX_SWIPE_DISTANCE, 0, 10] 
      : [-10, 0, MAX_SWIPE_DISTANCE, MAX_SWIPE_DISTANCE + 10],
    outputRange: isMe 
      ? [-MAX_SWIPE_DISTANCE, -MAX_SWIPE_DISTANCE, 0, 0] 
      : [0, 0, MAX_SWIPE_DISTANCE, MAX_SWIPE_DISTANCE],
    extrapolate: 'clamp',
  });
  const webLastTouchRef = useRef<{ x: number } | null>(null);

  const handleWebTouchStart = useCallback((e: any) => {
    const touch = e.nativeEvent?.touches?.[0] || e.nativeEvent;
    if (touch && touch.pageX !== undefined) {
      webTouchStartRef.current = { x: touch.pageX, time: Date.now() };
      webLastTouchRef.current = { x: touch.pageX };
    }
  }, []);

  const handleWebTouchMove = useCallback((e: any) => {
    const start = webTouchStartRef.current;
    if (!start) return;
    const touch = e.nativeEvent?.touches?.[0] || e.nativeEvent;
    if (!touch || touch.pageX === undefined) return;
    const dx = touch.pageX - start.x;
    const allowed = isMe ? dx < 5 : dx > -5;
    if (allowed) {
      webTranslateXRef.setValue(dx);
      webLastTouchRef.current = { x: touch.pageX };
    }
  }, [isMe]);

  const handleWebTouchEnd = useCallback((e: any) => {
    const start = webTouchStartRef.current;
    if (!start) return;
    webTouchStartRef.current = null;
    const touch = e.nativeEvent?.changedTouches?.[0] || e.nativeEvent;
    if (!touch || touch.pageX === undefined) {
      Animated.spring(webTranslateXRef, { toValue: 0, useNativeDriver: true }).start();
      return;
    }
    const dx = touch.pageX - start.x;
    const shouldTrigger = isMe 
      ? dx < -SWIPE_THRESHOLD
      : dx > SWIPE_THRESHOLD;
    
    if (shouldTrigger && !hasTriggeredRef.current) {
      hasTriggeredRef.current = true;
      onReply();
      setTimeout(() => {
        hasTriggeredRef.current = false;
      }, 300);
    }
    
    Animated.spring(webTranslateXRef, { toValue: 0, useNativeDriver: true }).start();
  }, [isMe, onReply]);

  if (!enabled) {
    return <>{children}</>;
  }

  if (Platform.OS === 'web') {
    return (
      <View style={styles.container}>
        <Animated.View
          style={[
            styles.replyIconContainer,
            isMe ? styles.replyIconLeft : styles.replyIconRight,
            { opacity: webIconOpacity },
          ]}
        >
          <MaterialCommunityIcons
            name="reply"
            size={20}
            color={colors.primary.main}
          />
        </Animated.View>
        <View
          data-gesture-area={true}
          onTouchStart={handleWebTouchStart}
          onTouchMove={handleWebTouchMove}
          onTouchEnd={handleWebTouchEnd}
        >
          <Animated.View
            style={{
              transform: [{ translateX: webClampedTranslateX }],
            }}
          >
            {children}
          </Animated.View>
        </View>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Animated.View
        style={[
          styles.replyIconContainer,
          isMe ? styles.replyIconLeft : styles.replyIconRight,
          { opacity: iconOpacity },
        ]}
      >
        <MaterialCommunityIcons
          name="reply"
          size={20}
          color={colors.primary.main}
        />
      </Animated.View>
      <PanGestureHandler
        onGestureEvent={onGestureEvent}
        onHandlerStateChange={onHandlerStateChange}
        activeOffsetX={isMe ? [-10, 9999] : [-9999, 10]}
        failOffsetY={[-20, 20]}
      >
        <Animated.View
          style={{
            transform: [{ translateX: clampedTranslateX }],
          }}
        >
          {children}
        </Animated.View>
      </PanGestureHandler>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    position: 'relative',
  },
  replyIconContainer: {
    position: 'absolute',
    top: '50%',
    marginTop: -15,
    width: 30,
    height: 30,
    borderRadius: 15,
    backgroundColor: 'rgba(255, 107, 53, 0.1)',
    alignItems: 'center',
    justifyContent: 'center',
  },
  replyIconLeft: {
    left: 8,
  },
  replyIconRight: {
    right: 8,
  },
});

export default SwipeableMessageBubble;