import React from 'react';

import {OnboardingStackParams} from '../../routes';
import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import {Background, RegistrationWizard, SubmitButton} from '../../components';
import {VERIFY_OTP_ENDPOINT, SEND_OTP_ENDPOINT} from '../../constants';
import {Text} from 'react-native-animatable';
import {
  CodeField,
  Cursor,
  useBlurOnFulfill,
  useClearByFocusCell,
} from 'react-native-confirmation-code-field';
import {
  StyleSheet,
  View,
  TouchableOpacity,
  KeyboardAvoidingView,
  Alert,
  ActivityIndicator,
} from 'react-native';
import {usePromiseTracker, trackPromise} from 'react-promise-tracker';

type VerificationScreenRouteProp = RouteProp<
  OnboardingStackParams,
  'Verification'
>;
type VerificationScreenNavigationProp = StackNavigationProp<
  OnboardingStackParams,
  'Verification'
>;
interface VerificationProps {
  route: VerificationScreenRouteProp;
  navigation: VerificationScreenNavigationProp;
}

const Verification: React.FC<VerificationProps> = ({route, navigation}) => {
  const [value, setValue] = React.useState('');
  const ref = useBlurOnFulfill({value, cellCount: 6});
  const [valueProps, getCellOnLayoutHandler] = useClearByFocusCell({
    value,
    setValue,
  });
  const {username, email, userId} = route.params;

  /**
   * Sends the verify_otp request upon tapping the Verify button.
   * If successful, it navigates to the Profile page.
   */
  const handleVerification = async () => {
    try {
      let verifyOtpResponse = await fetch(VERIFY_OTP_ENDPOINT, {
        method: 'POST',
        body: JSON.stringify({
          username: username,
          otp: value,
        }),
      });
      let statusCode = verifyOtpResponse.status;
      if (statusCode === 200) {
        navigation.navigate('Checkpoint', {
          userId: userId,
          username: username,
        });
      } else {
        Alert.alert(
          'Invalid verification code 🤔',
          'Try again. Tap the resend code button if you need a new code.',
        );
      }
    } catch (error) {
      Alert.alert(
        'Verifiation failed 😓',
        'Please double-check your network connection and retry.',
      );
      return {
        name: 'Verification error',
        description: error,
      };
    }
  };

  /**
   * Sends the send_otp request so to provide a new verification code upon tapping the Resend Code button.
   */
  const handleResend = async () => {
    try {
      let sendOtpResponse = await trackPromise(
        fetch(SEND_OTP_ENDPOINT, {
          method: 'POST',
          body: JSON.stringify({
            username: username,
            email: email,
          }),
        }),
      );
      let sendOtpStatusCode = sendOtpResponse.status;
      if (sendOtpStatusCode === 200) {
        setValue('');
        Alert.alert(
          'New verification code sent!',
          'Check your email for your code.',
        );
      } else {
        Alert.alert('Something went wrong!');
      }
    } catch (error) {
      console.log(error);
    }
  };

  /**
   * An activity indicator to indicate that the app is working during the send_otp request.
   */
  const LoadingIndicator = () => {
    const {promiseInProgress} = usePromiseTracker();
    return promiseInProgress ? (
      <ActivityIndicator
        style={styles.loadingIndicator}
        size="large"
        color="#fff"
      />
    ) : (
      <></>
    );
  };

  return (
    <Background centered style={styles.container}>
      <RegistrationWizard style={styles.wizard} step="three" />
      <KeyboardAvoidingView behavior="padding" style={styles.form}>
        <Text style={styles.formHeader}>Enter 6 digit code</Text>
        <Text style={styles.description}>
          We sent a 6 digit verification code to the email you provided.
        </Text>
        <CodeField
          ref={ref}
          {...valueProps}
          value={value}
          onChangeText={setValue}
          cellCount={6}
          rootStyle={styles.codeFieldRoot}
          keyboardType="number-pad"
          textContentType="oneTimeCode"
          renderCell={({index, symbol, isFocused}) => (
            <View
              onLayout={getCellOnLayoutHandler(index)}
              key={index}
              style={[styles.cellRoot, isFocused && styles.focusCell]}>
              <Text style={styles.cellText}>
                {symbol || (isFocused ? <Cursor /> : null)}
              </Text>
            </View>
          )}
        />
        <SubmitButton
          text="Verify"
          color="#fff"
          style={styles.button}
          accessibilityLabel="Verify"
          accessibilityHint="Select this after entering your email verification code"
          onPress={handleVerification}
        />
        <TouchableOpacity onPress={handleResend}>
          <Text style={styles.resend}>Resend Code</Text>
        </TouchableOpacity>
        <LoadingIndicator />
      </KeyboardAvoidingView>
    </Background>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  wizard: {
    marginTop: '3.5%',
    flex: 1,
    justifyContent: 'center',
  },
  form: {
    alignItems: 'center',
    justifyContent: 'flex-start',
    flex: 3,
  },
  formHeader: {
    color: '#fff',
    fontSize: 20,
    fontWeight: 'bold',
    alignSelf: 'flex-start',
    marginBottom: '6%',
    marginHorizontal: '10%',
  },
  description: {
    color: '#fff',
    fontWeight: '600',
    fontSize: 17,
    marginHorizontal: '10%',
  },
  resend: {
    textDecorationLine: 'underline',
    color: '#fff',
    fontSize: 15,
    fontWeight: '600',
  },
  codeFieldRoot: {
    width: 280,
    marginHorizontal: 'auto',
    marginVertical: '15%',
  },
  cellRoot: {
    width: 40,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    borderBottomColor: '#fff',
    borderBottomWidth: 1,
  },
  cellText: {
    color: '#fff',
    fontSize: 48,
    textAlign: 'center',
  },
  focusCell: {
    borderBottomColor: '#78a0ef',
    borderBottomWidth: 2,
  },
  button: {
    marginVertical: '5%',
  },
  loadingIndicator: {
    marginVertical: '5%',
  },
});
export default Verification;
