import { useRef, useState } from 'react';
import {
  View,
  Text,
  Image,
  Modal,
  TouchableOpacity,
  ActivityIndicator,
  StyleSheet,
  Dimensions,
} from 'react-native';
import {
  GestureDetector,
  Gesture,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
import { manipulateAsync, SaveFormat } from 'expo-image-manipulator';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTranslation } from 'react-i18next';
import { useColors } from '../../lib/theme';
import { AppAlert } from '../AppAlert';

const CROP_SIZE = Math.min(Dimensions.get('window').width - 48, 320);
const SPRING = { damping: 18, stiffness: 200 };

type Props = {
  imageUri: string | null;
  onConfirm: (croppedUri: string) => void;
  onCancel: () => void;
};

export function AvatarCropSheet({ imageUri, onConfirm, onCancel }: Props) {
  const { t } = useTranslation();
  const colors = useColors();
  const insets = useSafeAreaInsets();
  const [processing, setProcessing] = useState(false);
  const [uploadError, setUploadError] = useState<string | null>(null);

  const scale = useSharedValue(1);
  const savedScale = useSharedValue(1);
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);
  const savedTranslateX = useSharedValue(0);
  const savedTranslateY = useSharedValue(0);

  const pinch = Gesture.Pinch()
    .onUpdate((e) => {
      scale.value = Math.min(Math.max(savedScale.value * e.scale, 1), 5);
    })
    .onEnd(() => {
      savedScale.value = scale.value;
    });

  const pan = Gesture.Pan()
    .onUpdate((e) => {
      translateX.value = savedTranslateX.value + e.translationX;
      translateY.value = savedTranslateY.value + e.translationY;
    })
    .onEnd(() => {
      savedTranslateX.value = translateX.value;
      savedTranslateY.value = translateY.value;
    });

  const composed = Gesture.Simultaneous(pinch, pan);

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

  function reset() {
    scale.value = withSpring(1, SPRING);
    savedScale.value = 1;
    translateX.value = withSpring(0, SPRING);
    translateY.value = withSpring(0, SPRING);
    savedTranslateX.value = 0;
    savedTranslateY.value = 0;
  }

  async function handleConfirm() {
    if (!imageUri || processing) return;
    setProcessing(true);
    try {
      const result = await manipulateAsync(
        imageUri,
        [{ resize: { width: 512, height: 512 } }],
        { format: SaveFormat.JPEG, compress: 0.7 },
      );
      onConfirm(result.uri);
    } catch (e: any) {
      setUploadError(e?.message ?? t('alert.error_generic'));
    } finally {
      setProcessing(false);
    }
  }

  return (
    <Modal
      visible={!!imageUri}
      animationType="slide"
      presentationStyle="pageSheet"
      onRequestClose={onCancel}
    >
      <GestureHandlerRootView style={{ flex: 1 }}>
        <View style={[styles.container, { backgroundColor: colors.bg, paddingBottom: insets.bottom + 16 }]}>
          <View style={[styles.header, { borderBottomColor: colors.border }]}>
            <TouchableOpacity onPress={onCancel} hitSlop={10} activeOpacity={0.6} style={styles.headerBtn}>
              <Text style={[styles.headerBtnText, { color: colors.textMuted }]}>
                {t('common.cancel')}
              </Text>
            </TouchableOpacity>
            <Text style={[styles.headerTitle, { color: colors.text }]}>
              {t('profile.crop_title')}
            </Text>
            <TouchableOpacity
              onPress={handleConfirm}
              hitSlop={10}
              activeOpacity={0.6}
              style={styles.headerBtn}
              disabled={processing}
            >
              {processing ? (
                <ActivityIndicator size="small" color={colors.brandOrange} />
              ) : (
                <Text style={[styles.headerBtnText, { color: colors.brandOrange, fontFamily: 'Nunito_700Bold' }]}>
                  {t('profile.crop_confirm')}
                </Text>
              )}
            </TouchableOpacity>
          </View>

          <View style={styles.body}>
            <View style={[styles.cropFrame, { width: CROP_SIZE, height: CROP_SIZE }]}>
              <View style={styles.cropOverflow}>
                <GestureDetector gesture={composed}>
                  <Animated.View style={imageStyle}>
                    {imageUri ? (
                      <Image
                        source={{ uri: imageUri }}
                        style={{ width: CROP_SIZE, height: CROP_SIZE }}
                        resizeMode="cover"
                      />
                    ) : null}
                  </Animated.View>
                </GestureDetector>
              </View>

              <View style={styles.cornerTL} />
              <View style={styles.cornerTR} />
              <View style={styles.cornerBL} />
              <View style={styles.cornerBR} />
            </View>

            <Text style={[styles.hint, { color: colors.textMuted }]}>
              {t('profile.crop_hint')}
            </Text>

            <TouchableOpacity onPress={reset} activeOpacity={0.7} style={styles.resetBtn}>
              <Text style={[styles.resetText, { color: colors.textMuted }]}>
                {t('profile.crop_reset')}
              </Text>
            </TouchableOpacity>
          </View>
        </View>
      </GestureHandlerRootView>

      <AppAlert
        mode="error"
        visible={uploadError !== null}
        title={t('alert.compress_error_title')}
        message={uploadError ?? ''}
        onClose={() => setUploadError(null)}
      />
    </Modal>
  );
}

const CORNER = 18;
const BORDER = 2.5;

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 16,
    paddingVertical: 14,
    borderBottomWidth: StyleSheet.hairlineWidth,
  },
  headerTitle: {
    fontSize: 16,
    fontFamily: 'Nunito_700Bold',
  },
  headerBtn: {
    minWidth: 64,
    alignItems: 'center',
  },
  headerBtnText: {
    fontSize: 15,
    fontFamily: 'Nunito_600SemiBold',
  },
  body: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingHorizontal: 24,
    gap: 20,
  },
  cropFrame: {
    borderRadius: 12,
    overflow: 'hidden',
    position: 'relative',
    backgroundColor: '#111',
  },
  cropOverflow: {
    width: '100%',
    height: '100%',
    overflow: 'hidden',
  },
  cornerTL: {
    position: 'absolute',
    top: 0,
    left: 0,
    width: CORNER,
    height: CORNER,
    borderTopWidth: BORDER,
    borderLeftWidth: BORDER,
    borderColor: '#fff',
    borderTopLeftRadius: 12,
  },
  cornerTR: {
    position: 'absolute',
    top: 0,
    right: 0,
    width: CORNER,
    height: CORNER,
    borderTopWidth: BORDER,
    borderRightWidth: BORDER,
    borderColor: '#fff',
    borderTopRightRadius: 12,
  },
  cornerBL: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    width: CORNER,
    height: CORNER,
    borderBottomWidth: BORDER,
    borderLeftWidth: BORDER,
    borderColor: '#fff',
    borderBottomLeftRadius: 12,
  },
  cornerBR: {
    position: 'absolute',
    bottom: 0,
    right: 0,
    width: CORNER,
    height: CORNER,
    borderBottomWidth: BORDER,
    borderRightWidth: BORDER,
    borderColor: '#fff',
    borderBottomRightRadius: 12,
  },
  hint: {
    fontSize: 12,
    fontFamily: 'Nunito_400Regular',
    textAlign: 'center',
    lineHeight: 17,
  },
  resetBtn: {
    paddingVertical: 8,
    paddingHorizontal: 16,
  },
  resetText: {
    fontSize: 13,
    fontFamily: 'Nunito_600SemiBold',
  },
});
