import React, { useMemo, useRef, useCallback, useState } from 'react';
import { View, Pressable, StyleSheet, Dimensions } from 'react-native';
import CustomText from '@/components/common/CustomText.jsx';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { BottomSheetModal, BottomSheetBackdrop, BottomSheetView } from '@gorhom/bottom-sheet';
import { MoreHorizontal, X as XIcon, ChevronRight } from '@tamagui/lucide-icons';
import { wp } from '@/utils/ui/screenUtils';
import dialogService from '@/utils/ui/dialogService.js'
import * as Clipboard from 'expo-clipboard'
import { showSuccess } from '@/utils/ui/toast.js'
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, runOnJS } from 'react-native-reanimated';
import { GestureDetector, Gesture } from 'react-native-gesture-handler';
import * as Haptics from 'expo-haptics'
import { useTranslation } from '@/node_modules/react-i18next'

const FloatingMenu = ({ onRefreshCurrent, onRefreshInitial, onBackToApp, currentUrl, vconsoleEnabled, onToggleVConsole }) => {
  const insets = useSafeAreaInsets();
  const bottomSheetModalRef = useRef(null);
  const { t } = useTranslation();

  // 常量
  const RIGHT_MARGIN = wp(16);
  const { width: SCREEN_W, height: SCREEN_H } = Dimensions.get('window');
  const HIT_SLOP = useMemo(() => ({ top: wp(8), bottom: wp(8), left: wp(8), right: wp(8) }), []);

  // 悬浮窗隐藏/显示与箭头方向
  const translateX = useSharedValue(0);
  const hideOffset = useSharedValue(0);
  const isDocked = useSharedValue(false);
  const arrowFlip = useSharedValue(1);
  const arrowAnimatedStyle = useAnimatedStyle(() => ({
    transform: [{ scaleX: arrowFlip.value }],
  }));

  // 拖拽相关
  const posX = useSharedValue(0);
  const posY = useSharedValue(0);
  const startX = useSharedValue(0);
  const startY = useSharedValue(0);
  const groupW = useSharedValue(0);
  const groupH = useSharedValue(0);
  const isOnLeft = useSharedValue(false);
  const [isLeft, setIsLeft] = useState(false);
  // 移除帧跳过机制
  // const frameCounter = useSharedValue(0);

  // 使用 transform 替代 left/top，减少布局计算开销
  const positionStyle = useAnimatedStyle(() => ({ transform: [{ translateX: posX.value }, { translateY: posY.value }] }));
  const contentTranslateStyle = useAnimatedStyle(() => ({ transform: [{ translateX: translateX.value }] }));
  // 容器左右翻转（镜像）与箭头翻转补偿的实现已暂不启用，如需启用请在 JSX 中配合使用
  // const containerFlipStyle = useAnimatedStyle(() => ({ transform: [{ scaleX: isOnLeft.value ? -1 : 1 }] }));
  // const chevronStyle = useAnimatedStyle(() => ({ transform: [{ scaleX: (isOnLeft.value ? -1 : 1) * arrowFlip.value }] }));

  const onFloatGroupLayout = useCallback(({ nativeEvent: { layout } }) => {
    groupW.value = layout.width;
    groupH.value = layout.height;
    hideOffset.value = layout.width - RIGHT_MARGIN;
    if (posX.value === 0 && posY.value === 0) {
      posX.value = SCREEN_W - layout.width - RIGHT_MARGIN;
      posY.value = insets.top;
      isOnLeft.value = false;
      setIsLeft(false);
      arrowFlip.value = 1;
    }
  }, [SCREEN_W, insets.top]);

  const handleDockToggle = useCallback(() => {
    const toHide = !isDocked.value;
    const hideAmount = hideOffset.value;
    const target = toHide ? (isOnLeft.value ? -hideAmount : hideAmount) : 0;
    translateX.value = withTiming(target, { duration: 220, easing: Easing.out(Easing.cubic) });
    arrowFlip.value = withTiming(
      toHide ? (isOnLeft.value ? 1 : -1) : (isOnLeft.value ? -1 : 1),
      { duration: 220, easing: Easing.out(Easing.cubic) }
    );
    isDocked.value = toHide;
  }, []);

  // 拖拽 + 边缘吸附
  const dragPan = useMemo(
    () =>
      Gesture.Pan()
        .onBegin(() => {
          'worklet';
          startX.value = posX.value;
          startY.value = posY.value;
        })
        .onUpdate((event) => {
          'worklet';
          // 移除帧跳过：恢复每帧更新
          // frameCounter.value = (frameCounter.value + 1) % 2;
          // if (frameCounter.value !== 0) return;

          const nx = startX.value + event.translationX;
          const ny = startY.value + event.translationY;
          const yMin = insets.top;
          const yMax = SCREEN_H - groupH.value - insets.bottom;
          posX.value = nx;
          posY.value = Math.min(yMax, Math.max(yMin, ny));

          if (!isDocked.value) {
            const offLeftHalf = nx < -groupW.value / 2;
            const offRightHalf = nx > SCREEN_W - groupW.value / 2;
            if (offLeftHalf || offRightHalf) {
              const toLeft = offLeftHalf;
              isOnLeft.value = toLeft;
              const targetX = toLeft ? RIGHT_MARGIN : SCREEN_W - groupW.value - RIGHT_MARGIN;
              posX.value = withTiming(targetX, { duration: 200, easing: Easing.out(Easing.cubic) });
              translateX.value = withTiming(toLeft ? -hideOffset.value : hideOffset.value, { duration: 220, easing: Easing.out(Easing.cubic) });
              arrowFlip.value = withTiming(toLeft ? 1 : -1, { duration: 220, easing: Easing.out(Easing.cubic) });
              isDocked.value = true;
            }
          }
        })
        .onEnd(() => {
          'worklet';
          const midX = posX.value + groupW.value / 2;
          const toLeft = midX < SCREEN_W / 2;
          isOnLeft.value = toLeft;
          runOnJS(setIsLeft)(toLeft);
          const targetX = toLeft ? RIGHT_MARGIN : SCREEN_W - groupW.value - RIGHT_MARGIN;
          posX.value = withTiming(targetX, { duration: 220, easing: Easing.out(Easing.cubic) });
          if (isDocked.value) {
            translateX.value = withTiming(toLeft ? -hideOffset.value : hideOffset.value, { duration: 220, easing: Easing.out(Easing.cubic) });
            arrowFlip.value = withTiming(toLeft ? 1 : -1, { duration: 220, easing: Easing.out(Easing.cubic) });
          } else {
            arrowFlip.value = withTiming(toLeft ? -1 : 1, { duration: 160, easing: Easing.out(Easing.cubic) });
          }
        }),
    [SCREEN_W, SCREEN_H, insets.top, insets.bottom]
  );

  const snapPoints = useMemo(() => ['40%'], []);
  const fastAnimationConfigs = useMemo(() => ({ duration: 180, easing: Easing.out(Easing.cubic) }), []);

  const renderBackdrop = useCallback(
    (props) => (
      <BottomSheetBackdrop
        {...props}
        appearsOnIndex={0}
        disappearsOnIndex={-1}
        pressBehavior="close"
      />
    ),
    []
  );

  const openSheet = useCallback(() => { bottomSheetModalRef.current?.present(); }, []);

  const handleRefreshCurrentInternal = useCallback(() => {
    bottomSheetModalRef.current?.dismiss();
    onRefreshCurrent && onRefreshCurrent();
  }, [onRefreshCurrent]);

  const handleRefreshInitialInternal = useCallback(() => {
    bottomSheetModalRef.current?.dismiss();
    onRefreshInitial && onRefreshInitial();
  }, [onRefreshInitial]);

  const handleCancel = useCallback(() => { bottomSheetModalRef.current?.dismiss(); }, []);

  const handleBackInternal = useCallback(() => { onBackToApp && onBackToApp(); }, [onBackToApp]);

  const handleViewCurrentUrlInternal = useCallback(() => {
    bottomSheetModalRef.current?.dismiss();
    try {
      dialogService.confirm({
        content: (
          <View style={{ paddingHorizontal: wp(16), paddingVertical: wp(14) }}>
            <CustomText style={{ fontSize: wp(14), color: '#191919' }} selectable>
              {currentUrl || ''}
            </CustomText>
          </View>
        ),
        cancelText: t('webview:dialog.close'),
        confirmText: t('webview:dialog.copyLink'),
        onConfirm: async () => {
          try {
            await Clipboard.setStringAsync(String(currentUrl || ''))
            showSuccess(t('webview:toast.copiedCurrentUrl'))
          } catch (_) {}
        },
        width: wp(320),
        contentPadding: wp(0),
      })
    } catch (_) {}
  }, [currentUrl, t])

  const handleToggleVConsoleInternal = useCallback(() => {
    bottomSheetModalRef.current?.dismiss();
    try { onToggleVConsole && onToggleVConsole(); } catch (_) {}
  }, [onToggleVConsole])

  return (
    <View pointerEvents="box-none" style={StyleSheet.absoluteFill}>
      <Animated.View pointerEvents="box-none" style={[styles.floatWrap, positionStyle]}>
        <Animated.View pointerEvents="box-none" style={[styles.floatShadow, contentTranslateStyle]}>
          <GestureDetector gesture={dragPan}>
            <View style={styles.floatGroup} onLayout={onFloatGroupLayout}>
              {isLeft ? (
                <>
                  <Pressable
                    onPress={() => { Haptics.selectionAsync(); handleBackInternal(); }}
                    style={({ pressed }) => [styles.floatBtn, pressed && styles.floatBtnPressed]}
                    hitSlop={HIT_SLOP}
                  >
                    <XIcon size={wp(17)} color="#fff" />
                  </Pressable>
                  <View style={styles.divider} />
                  <Pressable
                    onPress={() => { Haptics.selectionAsync(); openSheet(); }}
                    style={({ pressed }) => [styles.floatBtn, pressed && styles.floatBtnPressed]}
                    hitSlop={HIT_SLOP}
                  >
                    <MoreHorizontal size={wp(17)} color="#fff" />
                  </Pressable>
                  <View style={styles.divider} />
                  <Pressable
                    onPress={() => { Haptics.selectionAsync(); handleDockToggle(); }}
                    style={({ pressed }) => [styles.floatBtn, pressed && styles.floatBtnPressed]}
                    hitSlop={HIT_SLOP}
                  >
                    <Animated.View style={arrowAnimatedStyle}>
                      <ChevronRight size={wp(17)} color="#fff" />
                    </Animated.View>
                  </Pressable>
                </>
              ) : (
                <>
                  <Pressable
                    onPress={() => { Haptics.selectionAsync(); handleDockToggle(); }}
                    style={({ pressed }) => [styles.floatBtn, pressed && styles.floatBtnPressed]}
                    hitSlop={HIT_SLOP}
                  >
                    <Animated.View style={arrowAnimatedStyle}>
                      <ChevronRight size={wp(17)} color="#fff" />
                    </Animated.View>
                  </Pressable>
                  <View style={styles.divider} />
                  <Pressable
                    onPress={() => { Haptics.selectionAsync(); openSheet(); }}
                    style={({ pressed }) => [styles.floatBtn, pressed && styles.floatBtnPressed]}
                    hitSlop={HIT_SLOP}
                  >
                    <MoreHorizontal size={wp(17)} color="#fff" />
                  </Pressable>
                  <View style={styles.divider} />
                  <Pressable
                    onPress={() => { Haptics.selectionAsync(); handleBackInternal(); }}
                    style={({ pressed }) => [styles.floatBtn, pressed && styles.floatBtnPressed]}
                    hitSlop={HIT_SLOP}
                  >
                    <XIcon size={wp(17)} color="#fff" />
                  </Pressable>
                </>
              )}
            </View>
          </GestureDetector>
        </Animated.View>
      </Animated.View>

      <BottomSheetModal
        ref={bottomSheetModalRef}
        snapPoints={snapPoints}
        backdropComponent={renderBackdrop}
        handleIndicatorStyle={{ backgroundColor: '#CFCFCF' }}
        backgroundStyle={{ backgroundColor: '#fff' }}
        animationConfigs={fastAnimationConfigs}
      >
        <BottomSheetView style={styles.sheetContainer}>
          <Pressable style={({ pressed }) => [styles.actionItem, pressed && styles.actionItemPressed]} onPress={handleRefreshCurrentInternal}>
            <CustomText style={styles.actionText}>{t('webview:menu.clearCacheReload')}</CustomText>
          </Pressable>
          <View style={styles.actionDivider} />
          <Pressable style={({ pressed }) => [styles.actionItem, pressed && styles.actionItemPressed]} onPress={handleRefreshInitialInternal}>
            <CustomText style={styles.actionText}>{t('webview:menu.backToInitialHardRefresh')}</CustomText>
          </Pressable>
          <View style={styles.actionDivider} />
          <Pressable style={({ pressed }) => [styles.actionItem, pressed && styles.actionItemPressed]} onPress={handleViewCurrentUrlInternal}>
            <CustomText style={styles.actionText}>{t('webview:menu.viewCurrentUrl')}</CustomText>
          </Pressable>
          <View style={styles.actionDivider} />
          <Pressable style={({ pressed }) => [styles.actionItem, pressed && styles.actionItemPressed]} onPress={handleToggleVConsoleInternal}>
            <CustomText style={styles.actionText}>{vconsoleEnabled ? t('webview:menu.closeVConsole', '关闭控制台(VConsole)') : t('webview:menu.openVConsole', '打开控制台(VConsole)')}</CustomText>
          </Pressable>
          <View style={styles.actionDivider} />
          <Pressable style={({ pressed }) => [styles.actionItem, pressed && styles.actionItemPressed]} onPress={handleCancel}>
            <CustomText style={styles.cancelText}>{t('webview:menu.cancel')}</CustomText>
          </Pressable>
          <View style={{ height: insets.bottom }} />
        </BottomSheetView>
      </BottomSheetModal>
    </View>
  );
};

export default React.memo(FloatingMenu);

const styles = StyleSheet.create({
  floatWrap: { position: 'absolute', zIndex: 10 },
  floatShadow: {
    borderRadius: wp(18),
    shadowColor: '#000',
    shadowOpacity: 0.18,
    shadowRadius: wp(6),
    shadowOffset: { width: wp(0), height: wp(3) },
    elevation: wp(4),
    // 移除渲染栅格化（此前反而导致卡顿）
    // renderToHardwareTextureAndroid: true,
    // shouldRasterizeIOS: true,
  },
  floatGroup: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'rgba(0,0,0,0.27)',
    borderRadius: wp(18),
    overflow: 'hidden',
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: 'rgba(255,255,255,0.18)',
  },
  floatBtn: {
    width: wp(34),
    height: wp(26),
    justifyContent: 'center',
    alignItems: 'center',
  },
  floatBtnPressed: { backgroundColor: 'rgba(255,255,255,0.08)' },
  divider: { width: StyleSheet.hairlineWidth, height: wp(10), backgroundColor: 'rgba(255,255,255,0.9)' },
  sheetContainer: { paddingHorizontal: wp(0), paddingTop: wp(0), paddingBottom: wp(0), backgroundColor: 'transparent' },
  actionItem: { height: wp(50), justifyContent: 'center', alignItems: 'center', width: '100%' },
  actionItemPressed: { backgroundColor: '#EDEDED' },
  actionText: { fontSize: wp(14), color: '#191919' },
  actionDivider: { height: StyleSheet.hairlineWidth, backgroundColor: '#E6E6E6', width: '100%' },
  cancelText: { fontSize: wp(14), color: '#666' },
});
