import { Text } from '@/aesthetics/Text';
import { colors } from '@/aesthetics/styles';
import { useStrings } from '@/common/hooks/useStrings';
import { Canvas, Group, Rect, RoundedRect, rect, rrect } from '@shopify/react-native-skia';
import { Camera as CameraIcon, CameraOff } from 'lucide-react-native';
import type { RefObject } from 'react';
import { useEffect, useState } from 'react';
import { Dimensions, Pressable, StyleSheet, View } from 'react-native';
import {
  GestureDetector,
  type ComposedGesture,
  type GestureType,
} from 'react-native-gesture-handler';
import Animated, {
  cancelAnimation,
  useAnimatedStyle,
  useDerivedValue,
  useSharedValue,
  withDelay,
  withSpring,
  withTiming,
  type SharedValue,
} from 'react-native-reanimated';
import {
  Camera as VisionCamera,
  type CameraDevice,
  type CameraDeviceFormat,
} from 'react-native-vision-camera';

const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
const CROP_RADIUS = 24;
const MASK_COLOR = colors.camera.cropMask;

type CropGestures = {
  cropResizeTL: GestureType;
  cropResizeTR: GestureType;
  cropResizeBL: GestureType;
  cropResizeBR: GestureType;
  cropResizeT: GestureType;
  cropResizeB: GestureType;
  cropResizeL: GestureType;
  cropResizeR: GestureType;
};

type CameraViewProps = {
  hasPermission: boolean;
  requestCameraPermission: () => void;
  device: CameraDevice | undefined;
  format: CameraDeviceFormat | undefined;
  cameraOn: boolean;
  cameraActive: boolean;
  cameraRef: RefObject<VisionCamera | null>;
  zoom: number;
  onInitialized: () => void;
  gesture: GestureType | ComposedGesture;
  showCropOverlay: boolean;
  cropGestures: CropGestures;
  cropBoxWidth: SharedValue<number>;
  cropBoxHeight: SharedValue<number>;
  cropAreaCenterY: number;
  onEnableCamera: () => void;
  focusPoint: { x: number; y: number } | null;
};

export function CameraView({
  hasPermission,
  requestCameraPermission,
  device,
  format,
  cameraOn,
  cameraActive,
  cameraRef,
  zoom,
  onInitialized,
  gesture,
  showCropOverlay,
  cropGestures,
  cropBoxWidth,
  cropBoxHeight,
  cropAreaCenterY,
  onEnableCamera,
  focusPoint,
}: CameraViewProps) {
  const strings = useStrings();

  const clip = useDerivedValue(() =>
    rrect(
      rect(
        (SCREEN_WIDTH - cropBoxWidth.value) / 2,
        cropAreaCenterY - cropBoxHeight.value / 2,
        cropBoxWidth.value,
        cropBoxHeight.value
      ),
      CROP_RADIUS,
      CROP_RADIUS
    )
  );

  const borderX = useDerivedValue(() => (SCREEN_WIDTH - cropBoxWidth.value) / 2);
  const borderY = useDerivedValue(() => cropAreaCenterY - cropBoxHeight.value / 2);

  const hitAreaStyle = useAnimatedStyle(() => ({
    position: 'absolute' as const,
    left: (SCREEN_WIDTH - cropBoxWidth.value) / 2,
    top: cropAreaCenterY - cropBoxHeight.value / 2,
    width: cropBoxWidth.value,
    height: cropBoxHeight.value,
  }));

  const [cropMounted, setCropMounted] = useState(false);
  useEffect(() => {
    if (!showCropOverlay) return;
    const id = requestAnimationFrame(() => setCropMounted(true));
    return () => {
      cancelAnimationFrame(id);
      setCropMounted(false);
    };
  }, [showCropOverlay]);

  const focusOpacity = useSharedValue(0);
  const focusScale = useSharedValue(1);

  useEffect(() => {
    if (focusPoint) {
      cancelAnimation(focusOpacity);
      cancelAnimation(focusScale);

      focusOpacity.value = 1;
      focusScale.value = 1.25;

      focusScale.value = withSpring(1, { damping: 30, stiffness: 500 });
      focusOpacity.value = withDelay(1000, withTiming(0, { duration: 500 }));
    }
  }, [focusPoint, focusOpacity, focusScale]);

  const focusIndicatorStyle = useAnimatedStyle(() => ({
    opacity: focusOpacity.value,
    transform: [{ scale: focusScale.value }],
  }));

  if (!hasPermission) {
    return (
      <Pressable style={styles.cameraPlaceholder} onPress={requestCameraPermission}>
        <CameraIcon size={48} color={colors.camera.text} />
        <Text style={styles.placeholderText}>{strings.addLog.camera.permissionNeeded}</Text>
        <View style={styles.permissionBtn}>
          <Text style={styles.permissionBtnText}>{strings.addLog.camera.enableCamera}</Text>
        </View>
      </Pressable>
    );
  }
  if (!device) {
    return (
      <View style={styles.cameraPlaceholder}>
        <CameraOff size={48} color={colors.camera.text} />
        <Text style={styles.placeholderText}>{strings.addLog.camera.noCameraAvailable}</Text>
      </View>
    );
  }
  return (
    <>
      <GestureDetector gesture={gesture}>
        <View style={styles.cameraContainer}>
          <VisionCamera
            ref={cameraRef}
            style={StyleSheet.absoluteFill}
            device={device}
            format={format}
            isActive={cameraActive}
            photo
            photoQualityBalance="speed"
            zoom={zoom}
            lowLightBoost={false}
            onInitialized={onInitialized}
          />
          {cropMounted && (
            <>
              <Canvas style={StyleSheet.absoluteFill} pointerEvents="none">
                <Group clip={clip} invertClip>
                  <Rect
                    x={0}
                    y={0}
                    width={SCREEN_WIDTH}
                    height={SCREEN_HEIGHT}
                    color={MASK_COLOR}
                  />
                </Group>
                <RoundedRect
                  x={borderX}
                  y={borderY}
                  width={cropBoxWidth}
                  height={cropBoxHeight}
                  r={CROP_RADIUS}
                  color={colors.camera.text}
                  style="stroke"
                  strokeWidth={2}
                />
              </Canvas>
              <Animated.View style={hitAreaStyle} pointerEvents="box-none">
                <GestureDetector gesture={cropGestures.cropResizeTL}>
                  <View style={styles.cropHitCornerTL} />
                </GestureDetector>
                <GestureDetector gesture={cropGestures.cropResizeTR}>
                  <View style={styles.cropHitCornerTR} />
                </GestureDetector>
                <GestureDetector gesture={cropGestures.cropResizeBL}>
                  <View style={styles.cropHitCornerBL} />
                </GestureDetector>
                <GestureDetector gesture={cropGestures.cropResizeBR}>
                  <View style={styles.cropHitCornerBR} />
                </GestureDetector>
                <GestureDetector gesture={cropGestures.cropResizeT}>
                  <View style={styles.cropHitEdgeT} />
                </GestureDetector>
                <GestureDetector gesture={cropGestures.cropResizeB}>
                  <View style={styles.cropHitEdgeB} />
                </GestureDetector>
                <GestureDetector gesture={cropGestures.cropResizeL}>
                  <View style={styles.cropHitEdgeL} />
                </GestureDetector>
                <GestureDetector gesture={cropGestures.cropResizeR}>
                  <View style={styles.cropHitEdgeR} />
                </GestureDetector>
              </Animated.View>
            </>
          )}
          {focusPoint && (
            <Animated.View
              style={[
                styles.focusIndicator,
                { left: focusPoint.x - 30, top: focusPoint.y - 30 },
                focusIndicatorStyle,
              ]}
              pointerEvents="none"
            />
          )}
        </View>
      </GestureDetector>
      {!cameraOn && <Pressable style={styles.cameraOffOverlay} onPress={onEnableCamera} />}
    </>
  );
}

const styles = StyleSheet.create({
  cameraContainer: {
    ...StyleSheet.absoluteFillObject,
    borderRadius: 24,
    overflow: 'hidden',
  },
  cameraPlaceholder: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: colors.camera.backgroundAlt,
    alignItems: 'center',
    justifyContent: 'center',
  },
  cameraOffOverlay: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: colors.camera.backgroundAlt,
  },
  placeholderText: { color: colors.camera.placeholderDim, fontSize: 16, marginTop: 12 },
  permissionBtn: {
    marginTop: 16,
    paddingHorizontal: 20,
    paddingVertical: 10,
    backgroundColor: colors.camera.permissionBg,
    borderRadius: 8,
  },
  permissionBtnText: { color: colors.camera.text, fontWeight: '600' },
  cropHitCornerTL: { position: 'absolute', top: -20, left: -20, width: 50, height: 50 },
  cropHitCornerTR: { position: 'absolute', top: -20, right: -20, width: 50, height: 50 },
  cropHitCornerBL: { position: 'absolute', bottom: -20, left: -20, width: 50, height: 50 },
  cropHitCornerBR: { position: 'absolute', bottom: -20, right: -20, width: 50, height: 50 },
  cropHitEdgeT: { position: 'absolute', top: -15, left: 50, right: 50, height: 30 },
  cropHitEdgeB: { position: 'absolute', bottom: -15, left: 50, right: 50, height: 30 },
  cropHitEdgeL: { position: 'absolute', left: -15, top: 50, bottom: 50, width: 30 },
  cropHitEdgeR: { position: 'absolute', right: -15, top: 50, bottom: 50, width: 30 },
  focusIndicator: {
    position: 'absolute',
    width: 60,
    height: 60,
    borderRadius: 30,
    borderWidth: 2,
    borderColor: colors.camera.focusBorder,
  },
});
