import { View, StyleSheet, Button, Text } from 'react-native';
import React, { memo, useCallback, useEffect, useState } from 'react';
import HintMessage from './HintMessage';
import { type GetIdSdk, GetidSdkTypes } from '@get-id/react-native-sdk';
import { DebugContext, DebugHelper } from '../../../src/contexts/debug-context';
import { useCropToBase64 } from '../helpers/debug';

type DocScanProps = {
  sdk: GetIdSdk;
  docType: 'front' | 'back';
  onNextStep?: () => void;
  onComplete?: () => void;
  onError?: (error: any) => void;
};

type DocScanFunctions = {
  takePicture?: Function;
  capture?: Function;
  uploadDocument?: () => Promise<GetidSdkTypes.ScannedDocument>;
};

const GetidFrontDocScanWrapper = ({
  sdk,
  onNextStep,
  onComplete,
  onError,
  docType,
}: DocScanProps) => {
  const [GetIdDocScanCmp, setGetIdDocScanCmp] = useState<React.JSX.Element>();
  const [hintMessage, setHintMessage] = useState<string>('');
  const [sdkFunctions, setSdkFunctions] = useState<DocScanFunctions>({});

  const [uploadingDoc, setUploadingDoc] = useState(false);

  const [captureClicked, setCaptureClicked] = useState(false);
  const [localError, setLocalError] = useState<any>(null);
  const [isCameraReady, setIsCameraReady] = useState(false);

  const onCameraReady = useCallback(() => {
    setIsCameraReady(true);
  }, []);

  const onUserHintChange = useCallback((hint: any) => {
    console.log(`onUserHintChange: ${hint}`);
    setHintMessage(hint);
  }, []);

  const onDocumentScanServerValidationStarted = useCallback(() => {
    console.log(
      'onDocumentScanServerValidationStarted: Document scan server validation started'
    );
  }, []);

  const handleScannedDocument = (
    scannedDocument: GetidSdkTypes.ScannedDocument
  ) => {
    console.log('Scanned Document:', scannedDocument);
    if (
      docType === 'front' &&
      scannedDocument.conclusion === 'back-side-missing'
    ) {
      return onNextStep?.();
    }
    if (scannedDocument.conclusion === 'ok') {
      // Once the document conclusion is ok, you can submit the document for verification
      return onComplete?.();
    }

    onUserHintChange(scannedDocument.conclusion);

    setUploadingDoc(false);
  };

  useEffect(() => {
    const initDocScan = async () => {
      const initialiseDocumentScan =
        docType === 'front'
          ? sdk.initialiseFrontDocumentScan
          : sdk.initialiseBackDocumentScan;

      try {
        const { component, ...functions } = await initialiseDocumentScan({
          onDocumentScanServerValidationStarted,
          onUserHintChange,
          onCameraReady,
          useAutoCapture: true,
          debugMode: false,
        });

        setGetIdDocScanCmp(() => component);
        setSdkFunctions(functions);
      } catch (e: any) {
        console.error('Error initialising face scan', e);
        onError?.(e);
      }
    };

    initDocScan();
  }, [
    sdk,
    onDocumentScanServerValidationStarted,
    onUserHintChange,
    onCameraReady,
    docType,
    onError,
  ]);

  const debugHelper = new DebugHelper();
  debugHelper.cropToBase64 = useCropToBase64(debugHelper.DEBUG_CROP_SIZE);

  return (
    <>
      {!isCameraReady && (
        <View style={styles.containerLoading}>
          <Text>Loading...</Text>
        </View>
      )}
      <View
        style={{
          ...styles.containerFullPage,
          ...(isCameraReady ? {} : styles.hiddenPage),
        }}
      >
        <DebugContext.Provider value={debugHelper}>
          {GetIdDocScanCmp}
        </DebugContext.Provider>

        <Text style={styles.titleDescription}>
          Please scan your {docType} document
        </Text>

        {uploadingDoc && <Text style={styles.textLoading}>Scanning...</Text>}
        {!uploadingDoc && !localError && <HintMessage message={hintMessage} />}
        {!uploadingDoc && localError && <HintMessage message={localError} />}

        <View style={styles.btnTakePicture}>
          <Button
            title="Capture"
            disabled={captureClicked}
            onPress={() => {
              setCaptureClicked(true);
              // subcribe to the capture promise, whenever the takePicture func is called, this promise will be resolved
              sdkFunctions.capture?.().then((scannedDocument: any) => {
                handleScannedDocument(scannedDocument);
                setCaptureClicked(false);
              });
            }}
          />
          <Button
            title="Upload from gallery"
            color={'green'}
            onPress={async () => {
              setUploadingDoc(true);
              setLocalError(null);

              try {
                const scannedDocument = await sdkFunctions.uploadDocument?.();
                handleScannedDocument(scannedDocument as any);
              } catch (error: any) {
                setUploadingDoc(false);
                setLocalError(error.message);
              }
            }}
          />
          <Button
            title="Take Picture"
            color={'green'}
            disabled={!captureClicked}
            onPress={async () => {
              setUploadingDoc(true);
              setLocalError(null);

              try {
                await sdkFunctions.takePicture?.();
              } catch (error: any) {
                setUploadingDoc(false);
                setLocalError(error.message);
              }
            }}
          />
        </View>
      </View>
    </>
  );
};

const styles = StyleSheet.create({
  containerFullPage: {
    flex: 1,
    justifyContent: 'flex-end',
  },
  containerLoading: {
    flex: 1,
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    zIndex: 100,
    backgroundColor: 'white',
  },
  hiddenPage: {
    opacity: 0,
  },
  btnTakePicture: {
    color: 'white',
    textAlign: 'center',
    marginBottom: 50,
    marginHorizontal: 10,
    // flexDirection: 'row',
    justifyContent: 'space-around',
    gap: 8,
  },
  textLoading: {
    color: 'white',
    fontSize: 24,
    textAlign: 'center',
    fontWeight: 'bold',
    marginBottom: 50,
  },
  titleDescription: {
    color: 'white',
    fontSize: 16,
    textAlign: 'center',
    fontWeight: 'bold',
    marginBottom: 'auto',
    marginTop: 80,
    alignSelf: 'center',
  },
});

export default memo(GetidFrontDocScanWrapper);
