import { CameraView, useCameraPermissions } from 'expo-camera';
import { manipulateAsync, SaveFormat } from 'expo-image-manipulator';
import { useRef, useState } from 'react';
import {
  ActivityIndicator,
  Alert,
  Pressable,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

const MAX_LONG_EDGE = 1200;

type Props = {
  onCaptured: (uri: string) => void;
};

export function CameraCapture({ onCaptured }: Props) {
  const [permission, requestPermission] = useCameraPermissions();
  const cameraRef = useRef<CameraView>(null);
  const [isCapturing, setIsCapturing] = useState(false);

  if (!permission) {
    return (
      <View style={styles.centered}>
        <ActivityIndicator size="large" color="#ffffff" />
      </View>
    );
  }

  if (!permission.granted) {
    return (
      <SafeAreaView style={styles.centered}>
        <Text style={styles.message}>
          レシートを撮影するためにカメラの使用許可が必要です。
        </Text>
        <Pressable
          style={({ pressed }) => [
            styles.permissionButton,
            pressed && styles.pressed,
          ]}
          onPress={requestPermission}>
          <Text style={styles.permissionButtonText}>カメラを許可する</Text>
        </Pressable>
      </SafeAreaView>
    );
  }

  const handleCapture = async () => {
    if (!cameraRef.current || isCapturing) return;
    try {
      setIsCapturing(true);
      const photo = await cameraRef.current.takePictureAsync({
        quality: 0.9,
        skipProcessing: false,
      });
      if (!photo?.uri) {
        throw new Error('画像の取得に失敗しました');
      }

      // アスペクト比を維持したまま長辺を 1200px 程度に縮小する。
      // サーバー送信時の通信負荷を下げる目的。
      const isPortrait = photo.height >= photo.width;
      const longEdge = Math.max(photo.width, photo.height);
      const resizeAction =
        longEdge > MAX_LONG_EDGE
          ? [
              {
                resize: isPortrait
                  ? { height: MAX_LONG_EDGE }
                  : { width: MAX_LONG_EDGE },
              },
            ]
          : [];

      const manipulated = await manipulateAsync(photo.uri, resizeAction, {
        compress: 0.8,
        format: SaveFormat.JPEG,
      });

      onCaptured(manipulated.uri);
    } catch (error) {
      console.error('[CameraCapture] 撮影に失敗:', error);
      Alert.alert(
        '撮影に失敗しました',
        'もう一度お試しください。問題が続く場合はアプリを再起動してください。'
      );
    } finally {
      setIsCapturing(false);
    }
  };

  return (
    <View style={styles.container}>
      <CameraView ref={cameraRef} style={StyleSheet.absoluteFill} facing="back" />
      <SafeAreaView style={styles.overlay} pointerEvents="box-none">
        <View style={styles.bottomBar}>
          <Pressable
            onPress={handleCapture}
            disabled={isCapturing}
            style={({ pressed }) => [
              styles.shutterOuter,
              (pressed || isCapturing) && styles.pressed,
            ]}
            accessibilityRole="button"
            accessibilityLabel="撮影する">
            <View style={styles.shutterInner}>
              {isCapturing ? (
                <ActivityIndicator size="small" color="#000" />
              ) : null}
            </View>
          </Pressable>
        </View>
      </SafeAreaView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000',
  },
  overlay: {
    flex: 1,
    justifyContent: 'flex-end',
  },
  centered: {
    flex: 1,
    backgroundColor: '#000',
    alignItems: 'center',
    justifyContent: 'center',
    padding: 24,
  },
  message: {
    color: '#fff',
    fontSize: 16,
    textAlign: 'center',
    marginBottom: 24,
    lineHeight: 24,
  },
  permissionButton: {
    backgroundColor: '#1f8ef1',
    paddingHorizontal: 32,
    paddingVertical: 14,
    borderRadius: 999,
  },
  permissionButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  bottomBar: {
    alignItems: 'center',
    paddingBottom: 24,
  },
  shutterOuter: {
    width: 88,
    height: 88,
    borderRadius: 44,
    borderWidth: 5,
    borderColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  shutterInner: {
    width: 68,
    height: 68,
    borderRadius: 34,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  pressed: {
    opacity: 0.7,
  },
});
