import AsyncStorage from '@react-native-community/async-storage';
import {useNavigation} from '@react-navigation/core';
import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import React, {useEffect, useState} from 'react';
import {
  Alert,
  KeyboardAvoidingView,
  Platform,
  StatusBar,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import {normalize} from 'react-native-elements';
import Animated, {Easing} from 'react-native-reanimated';
import {
  ArrowButton,
  Background,
  LoadingIndicator,
  TaggInput,
  TaggSquareButton,
  TermsConditions,
} from '../../components';
import {
  emailRegex,
  nameRegex,
  passwordRegex,
  phoneRegex,
  usernameRegex,
} from '../../constants';
import {
  ERROR_NEXT_PAGE,
  ERROR_PHONE_IN_USE,
  ERROR_REGISTRATION,
  ERROR_SOMETHING_WENT_WRONG_REFRESH,
  ERROR_TWILIO_SERVER_ERROR,
  ERROR_T_AND_C_NOT_ACCEPTED,
} from '../../constants/strings';
import {OnboardingStackParams} from '../../routes';
import {sendOtpStatusCode, sendRegister} from '../../services';
import {BackgroundGradientType} from '../../types';
import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';

type BasicInfoOnboardingRouteProp = RouteProp<
  OnboardingStackParams,
  'BasicInfoOnboarding'
>;
type BasicInfoOnboardingNavigationProp = StackNavigationProp<
  OnboardingStackParams,
  'BasicInfoOnboarding'
>;
interface BasicInfoOnboardingProps {
  route: BasicInfoOnboardingRouteProp;
  navigation: BasicInfoOnboardingNavigationProp;
}

const BasicInfoOnboarding: React.FC<BasicInfoOnboardingProps> = ({route}) => {
  const {isPhoneVerified} = route.params;
  const navigation = useNavigation();
  const [attemptedSubmit, setAttemptedSubmit] = useState(false);
  const [valid, setValid] = useState(false);
  const [currentStep, setCurrentStep] = useState(0);
  const [tcAccepted, setTCAccepted] = useState(false);
  const [passVisibility, setPassVisibility] = useState(false);
  const [autoCapitalize, setAutoCap] = useState('None');
  const [fadeValue, setFadeValue] = useState<Animated.Value<number>>(
    new Animated.Value(0),
  );
  const [form, setForm] = useState({
    fname: '',
    lname: '',
    username: '',
    phone: '',
    email: '',
    password: '',
  });

  const fadeComponentIn = async () => {
    Animated.timing(fadeValue, {
      toValue: 1,
      duration: 1000,
      easing: Easing.linear,
    }).start();
  };

  useEffect(() => {
    fadeComponentIn();
  }, [fadeValue]);

  const goNext = async () => {
    if (!attemptedSubmit) {
      setAttemptedSubmit(true);
    }
    try {
      if (valid) {
        const {phone} = form;
        const code = await sendOtpStatusCode(phone);
        if (code) {
          switch (code) {
            case 200:
              const {fname, lname} = form;
              navigation.navigate('PhoneVerification', {
                firstName: fname,
                lastName: lname,
                phone,
              });
              break;
            case 409:
              Alert.alert(ERROR_PHONE_IN_USE);
              break;
            default:
              Alert.alert(ERROR_TWILIO_SERVER_ERROR);
          }
        } else {
          setAttemptedSubmit(false);
          setTimeout(() => {
            setAttemptedSubmit(true);
          });
        }
      }
    } catch (error) {
      Alert.alert(ERROR_NEXT_PAGE);
      return {
        name: 'Navigation error',
        description: error,
      };
    }
  };
  // 0 = first name, 1 = last name, 2 = username, 3 = phone #
  const handleNameUpdate = (name: string, nameType: number) => {
    name = name.trim();
    let isValidName: boolean = nameRegex.test(name);
    switch (nameType) {
      case 0:
        setForm({
          ...form,
          fname: name,
        });
        setAutoCap('words');
        setValid(isValidName);
        break;
      case 1:
        setForm({
          ...form,
          lname: name,
        });
        setAutoCap('words');
        setValid(isValidName);
        break;
      case 2:
        setForm({
          ...form,
          username: name,
        });
        setValid(usernameRegex.test(name));
        setAutoCap('None');
        break;
    }
  };
  const handlePhoneUpdate = (phone: string) => {
    phone = phone.trim();
    setForm({
      ...form,
      phone,
    });
    setAutoCap('None');
    setValid(phoneRegex.test(phone));
  };
  const handleEmailUpdate = (email: string) => {
    email = email.trim();
    setForm({
      ...form,
      email,
    });
    setAutoCap('None');
    setValid(emailRegex.test(email));
  };
  const handlePasswordUpdate = (password: string) => {
    setForm({
      ...form,
      password,
    });
    setAutoCap('None');
    setValid(passwordRegex.test(password));
  };
  const formSteps: {
    placeholder: string;
    onChangeText: (text: string) => void;
  }[] = [
    {
      placeholder: 'First Name',
      onChangeText: (text) => handleNameUpdate(text, 0),
    },
    {
      placeholder: 'Last Name',
      onChangeText: (text) => handleNameUpdate(text, 1),
    },
    {
      placeholder: 'Phone',
      onChangeText: handlePhoneUpdate,
    },
    {
      placeholder: 'School Email',
      onChangeText: handleEmailUpdate,
    },
    {
      placeholder: 'Username',
      onChangeText: (text) => handleNameUpdate(text, 2),
    },
    {
      placeholder: 'Password',
      onChangeText: handlePasswordUpdate,
    },
  ];
  const resetForm = (formStep: String) => {
    setValid(false);
    switch (formStep) {
      case 'First Name':
        setForm({
          ...form,
          fname: '',
        });
        break;
      case 'Last Name':
        setForm({
          ...form,
          lname: '',
        });
        break;
      case 'Email':
        setForm({
          ...form,
          email: '',
        });
        break;
      case 'Password':
        setForm({
          ...form,
          password: '',
        });
        break;
      case 'School Email':
        setForm({
          ...form,
          email: '',
        });
        break;
      case 'Username':
        setForm({
          ...form,
          username: '',
        });
        break;
    }
  };
  const step = formSteps[currentStep];
  const advance = () => {
    setAttemptedSubmit(true);
    if (valid) {
      setCurrentStep(currentStep + 1);
      setAttemptedSubmit(false);
      setValid(false);
      setFadeValue(new Animated.Value(0));
    }
  };
  const advanceRegistration = async () => {
    setAttemptedSubmit(true);
    if (!valid) {
      return;
    }
    if (!tcAccepted) {
      Alert.alert('Terms and conditions', ERROR_T_AND_C_NOT_ACCEPTED);
      return;
    }
    const {fname, lname, phone, email, username, password} = form;
    const response = await sendRegister(
      fname,
      lname,
      phone,
      email,
      username,
      password,
    );
    if (response) {
      const data = await response.json();
      const {token, UserID} = data;
      switch (response.status) {
        case 201:
          await AsyncStorage.setItem('token', token);
          navigation.navigate('ProfileInfoOnboarding', {
            userId: UserID,
            username: username,
          });
          break;
        case 400:
          Alert.alert(ERROR_REGISTRATION(data.toLowerCase()));
          break;
        default:
          Alert.alert(ERROR_SOMETHING_WENT_WRONG_REFRESH);
          break;
      }
    } else {
      Alert.alert(ERROR_SOMETHING_WENT_WRONG_REFRESH);
    }
  };

  useEffect(() => {
    if (isPhoneVerified) {
      advance();
    }
  }, [isPhoneVerified]);

  return (
    <Background
      style={styles.container}
      gradientType={BackgroundGradientType.Light}>
      <StatusBar barStyle="light-content" />
      {/* getting rid of registration progress in onboarding*/}
      {/* <RegistrationWizard style={styles.wizard} step="one" /> */}
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
        style={styles.container}>
        <View style={styles.footer}>
          {currentStep !== 0 && currentStep !== 3 && (
            <ArrowButton
              style={styles.footer}
              direction="backward"
              onboarding={true}
              onPress={() => {
                // if I go back do I want to reset the previous form?
                setCurrentStep(currentStep - 1);
                resetForm(step.placeholder);
                setAttemptedSubmit(false);
              }}
            />
          )}
        </View>
        {step.placeholder === 'Phone' && !isPhoneVerified ? (
          <Animated.View style={{opacity: fadeValue}}>
            <TaggInput
              maxLength={10} // currently only support US phone numbers
              accessibilityHint="Enter your phone number."
              accessibilityLabel="Phone number input field."
              placeholder="Phone Number"
              autoCompleteType="tel"
              selectionColor="white"
              textContentType="telephoneNumber"
              autoCapitalize="none"
              externalStyles={{
                warning: styles.passWarning,
              }}
              keyboardType="number-pad"
              onChangeText={handlePhoneUpdate}
              autoFocus={true}
              blurOnSubmit={false}
              valid={valid}
              invalidWarning={'Please enter a valid 10 digit number.'}
              attemptedSubmit={attemptedSubmit}
              onSubmitEditing={goNext}
            />
            <TaggSquareButton
              onPress={goNext}
              title={'Verify'}
              buttonStyle={'normal'}
              buttonColor={'white'}
              labelColor={'blue'}
            />
          </Animated.View>
        ) : (
          <>
            {step.placeholder !== 'Password' ? (
              <>
                <Text style={styles.formHeader}>SIGN UP</Text>
                <Animated.View style={{opacity: fadeValue}}>
                  <TaggInput
                    key={step.placeholder}
                    style={styles.input}
                    accessibilityHint={`Enter your ${step.placeholder.toLowerCase()}`}
                    accessibilityLabel={`${step.placeholder} input field.`}
                    placeholder={step.placeholder}
                    autoCompleteType="name"
                    autoCapitalize="words"
                    textContentType="name"
                    returnKeyType="done"
                    selectionColor="white"
                    onChangeText={step.onChangeText}
                    onSubmitEditing={advance}
                    autoFocus={true}
                    blurOnSubmit={false}
                    externalStyles={{
                      warning: styles.passWarning,
                    }}
                    valid={valid}
                    invalidWarning={`Please enter a valid ${step.placeholder.toLowerCase()}`}
                    attemptedSubmit={attemptedSubmit}
                  />
                  <TaggSquareButton
                    onPress={advance}
                    title={'Next'}
                    buttonStyle={'normal'}
                    buttonColor={'white'}
                    labelColor={'blue'}
                  />
                </Animated.View>
              </>
            ) : (
              <Animated.View style={{opacity: fadeValue}}>
                <TaggInput
                  accessibilityHint="Enter a password."
                  accessibilityLabel="Password input field."
                  placeholder="Password"
                  autoCompleteType="password"
                  textContentType="oneTimeCode"
                  returnKeyType="next"
                  selectionColor="white"
                  onChangeText={handlePasswordUpdate}
                  onSubmitEditing={advanceRegistration}
                  blurOnSubmit={false}
                  secureTextEntry={!passVisibility}
                  valid={valid}
                  externalStyles={{
                    warning: styles.passWarning,
                  }}
                  invalidWarning={
                    'Password must be at least 8 characters & contain at least one of a-z, A-Z, 0-9, and a special character.'
                  }
                  attemptedSubmit={attemptedSubmit}
                  style={styles.input}
                />
                <TouchableOpacity
                  accessibilityLabel="Show password button"
                  accessibilityHint="Select this if you want to display your tagg password"
                  onPress={() => setPassVisibility(!passVisibility)}>
                  <Text style={styles.showPass}>Show Password</Text>
                </TouchableOpacity>
                <LoadingIndicator />
                <TermsConditions
                  style={styles.tc}
                  accepted={tcAccepted}
                  onChange={setTCAccepted}
                />
                <TaggSquareButton
                  onPress={advanceRegistration}
                  title={'Next'}
                  buttonStyle={'normal'}
                  buttonColor={'white'}
                  labelColor={'blue'}
                />
              </Animated.View>
            )}
          </>
        )}
      </KeyboardAvoidingView>
    </Background>
  );
};

const styles = StyleSheet.create({
  container: {
    height: SCREEN_HEIGHT,
    width: SCREEN_WIDTH,
    alignItems: 'center',
    justifyContent: 'center',
  },
  arrow: {
    color: '#6EE7E7',
  },
  showPass: {
    color: 'white',
    marginVertical: '1%',
    borderBottomWidth: 1,
    paddingBottom: '1%',
    left: '-18%',
    borderBottomColor: 'white',
    marginBottom: '8%',
  },
  passWarning: {
    fontSize: 14,
    marginTop: 5,
    color: '#FF8989',
    maxWidth: 350,
    alignSelf: 'flex-start',
  },
  input: {
    minWidth: '60%',
    height: 40,
    fontSize: 16,
    fontWeight: '600',
    color: '#fff',
    borderBottomWidth: 1,
    borderBottomColor: '#fff',
  },
  errorInput: {
    minWidth: '60%',
    height: 40,
    fontSize: 16,
    fontWeight: '600',
    color: '#FF8989',
    borderBottomWidth: 1,
    borderBottomColor: '#fff',
  },
  button: {
    alignItems: 'center',
    width: 40,
    aspectRatio: 10,
  },
  formHeader: {
    color: '#fff',
    fontSize: 30,
    fontWeight: '600',
    position: 'absolute',
    top: '20%',
  },
  load: {
    top: '5%',
  },
  tc: {
    marginVertical: '5%',
  },
  footer: {
    height: normalize(50),
    width: normalize(50),
    flexDirection: 'row',
    justifyContent: 'space-around',
    ...Platform.select({
      ios: {
        bottom: '20%',
      },
      android: {
        bottom: '10%',
      },
    }),
  },
});
export default BasicInfoOnboarding;
