import {
  Text,
  View,
  Pressable,
  Image,
  Platform,
  ActivityIndicator,
} from 'react-native';
import React, {useEffect, useRef, useState} from 'react';
import {Animated} from 'react-native';
import {styles} from './styles';

import {globalStyles} from '../../../globalStyles';
import CaptureButton from '../../design-system/capture-button/capture-button.component';
import FlipButton from '../../design-system/flip-button/flip-button.component';
import Icon from 'react-native-vector-icons/Ionicons';
import {
  Camera,
  CameraDeviceFormat,
  useCameraDevice,
  useCameraDevices,
  useFrameProcessor,
} from 'react-native-vision-camera';
import {getBranding} from '../../branding';
import Spinner from 'react-native-loading-spinner-overlay';
import overlayImage from '../../assets/faceki-overlay-camera-L2.png';
import guideImage from '../../assets/MFXiWh.png';
import branding from '../../branding';
import axios, {AxiosResponse} from 'axios';
import Toast from 'react-native-toast-message';
import ImageResizer from '@bam.tech/react-native-image-resizer';
import {useMyStepsVerification} from '../../provider/verification.context';
import RNFS from 'react-native-fs';

const IDCARD = '../../assets/idwhite.png';

const DLCARD = '../../assets/dlwhite.png';
const Passport = '../../assets/passportwhite.png';

const Resizer = require('@bam.tech/react-native-image-resizer');

type props = {
  webcamRef: React.MutableRefObject<any>;
  handleSingleCapturePhoto: (
    step: number,
    image?: any,
    refOverride?: any,
  ) => void;
  userStep: number;
  skipGuidanceScreens?: boolean;
  livenessScoreOverride?: number | null | undefined;
  goBackUserSteps: (index?: number) => void;
  findOutStepContent: () => {
    step: number;
    heading: string;
    subHeading: string;
  };
};

/**
 * A component for capturing an image of the user with the device's camera.
 *
 * @param {Object} props - The component props.
 * @param {string} props.cameraMode - The type of camera to use (front or back).
 * @param {Function} props.flipCamera - A function that switches between the front and back camera.
 * @param {Object} props.webcamRef - A mutable ref object for accessing the camera component.
 * @param {Function} props.handleSingleCapturePhoto - A function that handles capturing a single photo for the current verification step.
 * @param {number} props.userStep - The current step in the user verification process.
 * @returns {JSX.Element} - The rendered component as a JSX element.
 */

const CaptureUserWebcam = ({
  webcamRef,
  handleSingleCapturePhoto,
  userStep,
  goBackUserSteps,
  findOutStepContent,
  skipGuidanceScreens,
  livenessScoreOverride,
}: props) => {
  const context = useMyStepsVerification();
  const { t } = context;

  const devices: any = useCameraDevices();
  const device = useCameraDevice('back', {
    physicalDevices: [
      'ultra-wide-angle-camera',
      'wide-angle-camera',
      'telephoto-camera',
    ],
  });
  const [loading, setLoading] = useState(false);
  const [lowResWarned, setLowResWarned] = useState(false);
  const [cameraReady, setCameraReady] = useState(false);
  const [showGuide, setShowGuide] = useState(true);
  const guideOpacity = useRef(new Animated.Value(1)).current;
  const tets = useRef<any | null>(null);
  var form: FormData | undefined;

  // Delay camera activation to let Android release previous camera session
  useEffect(() => {
    const timer = setTimeout(() => setCameraReady(true), Platform.OS === 'android' ? 300 : 100);
    return () => clearTimeout(timer);
  }, []);

  // Show guide image for 3s then fade out
  useEffect(() => {
    const fadeTimer = setTimeout(() => {
      Animated.timing(guideOpacity, {
        toValue: 0,
        duration: 500,
        useNativeDriver: true,
      }).start(() => setShowGuide(false));
    }, 3000);
    return () => clearTimeout(fadeTimer);
  }, []);

  useEffect(() => {
    async function name() {
      try {
        var te = await tets?.current?.takePhoto?.({
          enableShutterSound: false,
          // enableAutoStabilization: true,
          qualityPrioritization: 'speed',
        });

        if (!te) {
          // console.log('Photo capture failed');

          return;
        }
        if (!te.path) {
          // console.log('Photo capture failed');
          return;
        }

        // Check actual photo resolution from the device
        if (!lowResWarned && te.width && te.height) {
          const w = Math.max(te.width, te.height);
          const h = Math.min(te.width, te.height);
          if (w < 1920 && h < 1080) {
            setLowResWarned(true);
            Toast.show({
              type: 'info',
              text1: t.lowCameraResolution,
              text2: t.lowCameraMsg.replace('{w}', String(w)).replace('{h}', String(h)),
              visibilityTime: 5000,
            });
          }
        }

        form = new FormData();
        form.append('image', {
          uri: Platform.OS == 'android' ? 'file://' + te?.path : te?.path,
          type: 'image/jpeg',
          name: `photo_id_back_image.jpg`,
        });

        console.log(te?.path);
      } catch (error) {
        setTimeout(name, Platform.OS == 'android' ? 100 : 1500); // Retry after 700ms
      }

      try {
        const response = await axios.post(
          'https://addon.faceki.com/detect',
          form,
          {
            headers: {'Content-Type': 'multipart/form-data'},
          },
        );
        const objectsDetected = response?.data?.objects_detected?.length;
        console.log(response?.data);

        if (objectsDetected < 1) {
          setTimeout(name, Platform.OS == 'android' ? 100 : 1500); // Retry after 700ms
        } else {
          handleSingleCapturePhoto(userStep, te);
        }
      } catch (error: any) {
        console.error('API request failed:', JSON.stringify(error));
        // Handle the error or retry if needed
        setTimeout(name, Platform.OS == 'android' ? 100 : 1500); // Retry after 700ms
      }
    }
    // setTimeout(() => {
    //   name();
    // }, 3000);
  }, []);

  const HandleCapture = async () => {
    let te: any;
    let response: AxiosResponse | undefined;
    try {
      // {userStep === 7 ? 'BACK SIDE' : 'FRONT SIDE'}
      te = await tets?.current?.takePhoto?.({
        enableShutterSound: false,
        // enableAutoStabilization: true,
        qualityPrioritization: 'quality',
      });

      if (!te?.path) {
        setLoading(false);
        Toast.show({
          type: 'error',
          text1: t.captureFailed,
          text2: t.captureFailedMsg,
        });
        return;
      }

      try {
        // 10MB limit per document combo (front + back + selfie)
        // Budget per doc image: ~3.2MB leaves room for selfie
        const MAX_BYTES = 3.2 * 1024 * 1024;
        let quality = 100;
        let result = await Resizer.default.createResizedImage(
          (Platform.OS === 'android' ? 'file://' : '') + te.path,
          1920,
          1080,
          'JPEG',
          quality,
          0,
          undefined,
          false,
          {mode: 'contain'},
        );

        // If file exceeds budget, re-compress at lower quality
        if (result.size > MAX_BYTES) {
          quality = Math.max(40, Math.floor((MAX_BYTES / result.size) * 100));
          result = await Resizer.default.createResizedImage(
            (Platform.OS === 'android' ? 'file://' : '') + te.path,
            1920,
            1080,
            'JPEG',
            quality,
            0,
            undefined,
            false,
            {mode: 'contain'},
          );
        }
        console.log(`Image resized: ${(result.size / 1024).toFixed(0)}KB @ quality ${quality}`);
        te = result;
      } catch (error) {
        console.log(error);
      }

      const imageUri = Platform.OS == 'android' ? 'file://' + te?.path : te?.path;
      console.log(`Uploading image: ${imageUri}, size: ${te?.size ? (te.size / 1024).toFixed(0) + 'KB' : 'unknown'}`);

      const MAX_RETRIES = 2;
      for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
        try {
          // Rebuild FormData each attempt — Android streams are consumed on first use
          const uploadForm = new FormData();
          uploadForm.append('image', {
            uri: imageUri,
            type: 'image/jpeg',
            name: `photo_id_back_image.jpg`,
          });
          response = await axios.post(
            'https://addon.faceki.com/advance/detect',
            uploadForm,
            {
              headers: {'Content-Type': 'multipart/form-data'},
              timeout: 30000,
            },
          );
          break;
        } catch (uploadErr: any) {
          console.warn(`Upload attempt ${attempt + 1} failed:`, uploadErr?.message);
          if (attempt === MAX_RETRIES) throw uploadErr;
          await new Promise(r => setTimeout(r, 1000));
        }
      }

      console.log('Detection Response', response);

      if (
        response?.data?.liveness?.livenessScore &&
        response.data.liveness.livenessScore > (livenessScoreOverride || 0.7)
      ) {
        setLoading(false);
        handleSingleCapturePhoto(userStep, te);
      } else {
        setLoading(false);
        Toast.show({
          type: 'error',
          text1: t.pleaseTryAgain,
          text2: t.imageQualityFail,
        });
        if (context.onLivenessError && te?.path) {
          try {
            const base64 = await RNFS.readFile(te.path, 'base64');
            context.onLivenessError('data:image/jpeg;base64,' + base64, JSON.stringify(response?.data));
          } catch (readErr) {
            console.error('base64 read failed (liveness):', readErr);
          }
        }
      }
    } catch (error: any) {
      // console.error('HandleCapture error:', error?.message || error, error?.response?.status, error?.code);
      setLoading(false);
      Toast.show({
        type: 'error',
        text1: t.somethingWentWrong,
        text2: t.tryCapturingAgain,
      });
      if (context.onLivenessError && te?.path) {
        try {
          const base64 = await RNFS.readFile(te.path, 'base64');
          context.onLivenessError(
            'data:image/jpeg;base64,' + base64,
            response?.data ? JSON.stringify(response.data) : JSON.stringify(error),
          );
        } catch (readErr) {
          console.error('base64 read failed (catch):', readErr);
        }
      }
    }
  };

  return (
    <View key="main" style={{flex: 1}}>
      {/* Camera Screen */}

      {device && cameraReady && (
        <Camera
          style={[styles.overlayContainer, {flex: 1, width: '100%', zIndex: 1}]}
          device={device}
          isActive={true}
          ref={tets}
          photo={true}
          video={true}
          key={`cam-${userStep}`}
        />
      )}

      {/* Tap-to-focus layer */}
      <Pressable
        style={{
          position: 'absolute',
          top: 0,
          left: 0,
          width: '100%',
          height: '100%',
          zIndex: 2,
        }}
        onPress={(e) => {
          if (tets.current?.focus) {
            try {
              tets.current.focus({ x: e.nativeEvent.locationX, y: e.nativeEvent.locationY });
            } catch (_) {}
          }
        }}>
        {/* Overlay Image Screen */}
        <Image
          source={overlayImage}
          style={styles.overlayImage}
          resizeMode="cover"
        />
      </Pressable>



      {/* Camera icon hint in center of frame */}
      {!loading && (
        <View
          pointerEvents="none"
          style={{
            position: 'absolute',
            top: 0,
            left: 0,
            right: 0,
            bottom: 0,
            justifyContent: 'center',
            alignItems: 'center',
            zIndex: 2,
          }}>
          <Icon
            name="camera-outline"
            size={48}
            color={'rgba(255,255,255,0.5)'}
          />
          <Text
            style={[
              globalStyles.textMedium,
              {
                color: 'rgba(255,255,255,0.5)',
                fontSize: 13,
                marginTop: 8,
              },
            ]}>
            {t.placeDocument}
          </Text>
        </View>
      )}
      <Spinner
        visible={loading}
        textContent={t.analyzing}
        textStyle={{color: 'white'}}
      />
      {/* Header Component */}

      <View key="topContent" style={styles.topContent}>
        <Pressable
          key={'gobackButton'}
          onPress={() => {
            skipGuidanceScreens && userStep != 7
              ? goBackUserSteps(2)
              : goBackUserSteps();
          }}
          style={({pressed}) => pressed && styles.opacity}>
          <Icon name="arrow-back" size={30} color={'white'} />
        </Pressable>

        <View key={'con'} style={{alignItems: 'center'}}>
          <Text
            key={'heading1'}
            style={[
              styles.heading,
              globalStyles.textMedium,
              {
                color:
                  getBranding().colors.title_camera_color ||
                  getBranding().colors.primary,
                fontSize: 18,
                fontWeight: 700,
              },
            ]}>
            {findOutStepContent()?.heading}
          </Text>
          <Text
            key={'heading2'}
            style={[
              styles.subheading,
              globalStyles.textMedium,
              {color: 'white', marginTop: 7},
            ]}>
            {findOutStepContent()?.subHeading}
          </Text>
          <View
            style={{
              flex: 1,
              flexDirection: 'row',
              justifyContent: 'center',
              alignItems: 'flex-start',
              marginTop: '10%',
            }}>
            <View
              style={{
                flex: 1,
                flexDirection: 'row',
                justifyContent: 'center',
                alignItems: 'center',
                // marginLeft: findOutStepContent()?.heading.includes('Driving') ? "14%" : 4,
              }}>
              <Image
                style={{
                  width: 30,
                  height: 30,
                  objectFit: 'contain',
                  marginRight: 7,
                }}
                source={
                  context.selectedOption?.includes('ID Card')
                    ? require(IDCARD)
                    : context.selectedOption?.includes('Passport')
                    ? require(Passport)
                    : require(DLCARD)
                }
              />
              <Text
                key={'subtitle'}
                style={[
                  styles.subheading,
                  globalStyles.textMedium,
                  {
                    color:
                      getBranding().colors.title_camera_color ||
                      getBranding().colors.primary,
                    fontSize: 18,
                    fontWeight: '700',
                  },
                ]}>
                {userStep === 7 ? t.backSide : t.frontSide}
              </Text>
            </View>
          </View>
        </View>

        {context.onCancel ? (
          <Pressable
            key={'close'}
            onPress={context.onCancel}
            style={({pressed}) => pressed && styles.opacity}>
            <Icon name="close" size={30} color={'white'} style={{marginTop: 10}} />
          </Pressable>
        ) : (
          <View key={'close-placeholder'} style={{width: 30}} />
        )}
      </View>

      {/* Footer Component */}

      <View
        key="bottomContent"
        style={[styles.captureButtonContainer, {zIndex: 9999}]}>
        <View style={styles.buttonRow}>
          <View key={'capture'} style={styles.captureButtonWrapper}>
            <CaptureButton
              onClick={() => {
                setLoading(true);
                HandleCapture();
              }}
            />
          </View>
        </View>
      </View>
    </View>
  );
};

export default CaptureUserWebcam;
