import React from 'react';
import {RouteProp} from '@react-navigation/native';
import moment from 'moment';
import {StackNavigationProp} from '@react-navigation/stack';
import {
  Text,
  StatusBar,
  StyleSheet,
  Image,
  TouchableOpacity,
  Alert,
  View,
} from 'react-native';
import {
  Background,
  TaggBigInput,
  TaggInput,
  TaggDropDown,
  BirthDatePicker,
} from '../../components';
import {OnboardingStackParams} from '../../routes/onboarding';
import ImagePicker from 'react-native-image-crop-picker';
import {
  EDIT_PROFILE_ENDPOINT,
  websiteRegex,
  bioRegex,
  genderRegex,
  CLASS_YEAR_LIST,
} from '../../constants';
import AsyncStorage from '@react-native-community/async-storage';
import {BackgroundGradientType} from '../../types';
import {PickerSelectProps} from 'react-native-picker-select';
import Animated from 'react-native-reanimated';
import {SCREEN_WIDTH} from '../../utils';
import {
  ERROR_DOUBLE_CHECK_CONNECTION,
  ERROR_PROFILE_CREATION_SHORT,
  ERROR_SELECT_CLASS_YEAR,
  ERROR_SOMETHING_WENT_WRONG_REFRESH,
  ERROR_UPLOAD_LARGE_PROFILE_PIC,
  ERROR_UPLOAD_SMALL_PROFILE_PIC,
} from '../../constants/strings';

type ProfileOnboardingScreenRouteProp = RouteProp<
  OnboardingStackParams,
  'ProfileOnboarding'
>;
type ProfileOnboardingScreenNavigationProp = StackNavigationProp<
  OnboardingStackParams,
  'ProfileOnboarding'
>;
interface ProfileOnboardingProps {
  route: ProfileOnboardingScreenRouteProp;
  navigation: ProfileOnboardingScreenNavigationProp;
}

/**
 * Create profile screen for onboarding.
 * @param navigation react-navigation navigation object
 */

const ProfileOnboarding: React.FC<ProfileOnboardingProps> = ({
  route,
  navigation,
}) => {
  const {userId, username} = route.params;
  let emptyDate: string | undefined;
  const [form, setForm] = React.useState({
    largePic: '',
    smallPic: '',
    website: '',
    bio: '',
    birthdate: emptyDate,
    gender: '',
    isValidWebsite: true,
    isValidBio: true,
    isValidGender: true,
    attemptedSubmit: false,
    token: '',
    classYear: -1,
  });
  const [customGender, setCustomGender] = React.useState(Boolean);

  // refs for changing focus
  const bioRef = React.useRef();
  const birthdateRef = React.useRef();
  const genderRef = React.useRef();
  const customGenderRef = React.useRef();
  /**
   * Handles focus change to the next input field.
   * @param field key for field to move focus onto
   */
  const handleFocusChange = (field: string): void => {
    switch (field) {
      case 'bio':
        const bioField: any = bioRef.current;
        bioField.focus();
        break;
      case 'birthdate':
        const birthdateField: any = birthdateRef.current;
        birthdateField.focus();
        break;
      case 'gender':
        const genderField: any = genderRef.current;
        genderField.focus();
        break;
      case 'customGender':
        const customGenderField: any = customGenderRef.current;
        customGenderField.focus();
        break;
      default:
        return;
    }
  };

  var classYearList: Array<any> = [];

  CLASS_YEAR_LIST.map((value) => {
    classYearList.push({label: value, value: value});
  });

  /**
   * Profile screen "Add header image" button
   */
  const LargeProfilePic = () => (
    <TouchableOpacity
      accessible={true}
      accessibilityLabel="ADD HEADER IMAGE"
      onPress={goToGalleryLargePic}
      style={styles.largeProfileUploader}>
      {form.largePic ? (
        <Image source={{uri: form.largePic}} style={styles.largeProfilePic} />
      ) : (
        <Text style={styles.largeProfileText}>ADD HEADER IMAGE</Text>
      )}
    </TouchableOpacity>
  );

  /**
   * Profile screen "Add profile picture" button
   */
  const SmallProfilePic = () => (
    <TouchableOpacity
      accessible={true}
      accessibilityLabel="ADD PROFILE PICTURE"
      onPress={goToGallerySmallPic}
      style={styles.smallProfileUploader}>
      {form.smallPic ? (
        <Image source={{uri: form.smallPic}} style={styles.smallProfilePic} />
      ) : (
        <Text style={styles.smallProfileText}>ADD PROFILE PICTURE</Text>
      )}
    </TouchableOpacity>
  );

  const goToGalleryLargePic = () => {
    ImagePicker.openPicker({
      smartAlbums: [
        'Favorites',
        'RecentlyAdded',
        'SelfPortraits',
        'Screenshots',
        'UserLibrary',
      ],
      width: 580,
      height: 580,
      cropping: true,
      cropperToolbarTitle: 'Select Header',
      mediaType: 'photo',
    }).then((picture) => {
      if ('path' in picture) {
        setForm({
          ...form,
          largePic: picture.path,
        });
      }
    });
  };

  const goToGallerySmallPic = () => {
    ImagePicker.openPicker({
      smartAlbums: [
        'Favorites',
        'RecentlyAdded',
        'SelfPortraits',
        'Screenshots',
        'UserLibrary',
      ],
      width: 580,
      height: 580,
      cropping: true,
      cropperToolbarTitle: 'Select Profile Picture',
      mediaType: 'photo',
      cropperCircleOverlay: true,
    }).then((picture) => {
      if ('path' in picture) {
        setForm({
          ...form,
          smallPic: picture.path,
        });
      }
    });
  };

  /*
   * Handles changes to the website field value and verifies the input by updating state and running a validation function.
   */
  const handleWebsiteUpdate = (website: string) => {
    website = website.trim();
    let isValidWebsite: boolean = websiteRegex.test(website);
    setForm({
      ...form,
      website,
      isValidWebsite,
    });
  };

  /*
   * Handles changes to the bio field value and verifies the input by updating state and running a validation function.
   */
  const handleBioUpdate = (bio: string) => {
    let isValidBio: boolean = bioRegex.test(bio);
    setForm({
      ...form,
      bio,
      isValidBio,
    });
  };

  const handleGenderUpdate = (gender: string) => {
    if (gender === 'custom') {
      setCustomGender(true);
    } else {
      setCustomGender(false);
      let isValidGender: boolean = true;
      setForm({
        ...form,
        gender,
        isValidGender,
      });
    }
  };

  const handleClassYearUpdate = (value: string) => {
    const classYear = Number.parseInt(value);
    setForm({
      ...form,
      classYear,
    });
  };

  const handleCustomGenderUpdate = (gender: string) => {
    let isValidGender: boolean = genderRegex.test(gender);
    gender = gender.replace(' ', '-');
    setForm({
      ...form,
      gender,
      isValidGender,
    });
  };

  const handleBirthdateUpdate = (birthdate: Date) => {
    setForm({
      ...form,
      birthdate: birthdate && moment(birthdate).format('YYYY-MM-DD'),
    });
  };

  const handleSubmit = async () => {
    if (!form.largePic) {
      Alert.alert(ERROR_UPLOAD_LARGE_PROFILE_PIC);
      return;
    }
    if (!form.smallPic) {
      Alert.alert(ERROR_UPLOAD_SMALL_PROFILE_PIC);
      return;
    }
    if (form.classYear === -1) {
      Alert.alert(ERROR_SELECT_CLASS_YEAR);
      return;
    }
    if (!form.attemptedSubmit) {
      setForm({
        ...form,
        attemptedSubmit: true,
      });
    }
    let invalidFields: boolean = false;
    const request = new FormData();
    if (form.largePic) {
      request.append('largeProfilePicture', {
        uri: form.largePic,
        name: 'large_profile_pic.jpg',
        type: 'image/jpg',
      });
    }
    if (form.smallPic) {
      request.append('smallProfilePicture', {
        uri: form.smallPic,
        name: 'small_profile_pic.jpg',
        type: 'image/jpg',
      });
    }
    if (form.website) {
      if (form.isValidWebsite) {
        request.append('website', form.website);
      } else {
        setForm({...form, attemptedSubmit: false});
        setTimeout(() => setForm({...form, attemptedSubmit: true}));
        invalidFields = true;
      }
    }

    if (form.bio) {
      if (form.isValidBio) {
        request.append('biography', form.bio);
      } else {
        setForm({...form, attemptedSubmit: false});
        setTimeout(() => setForm({...form, attemptedSubmit: true}));
        invalidFields = true;
      }
    }

    if (form.birthdate) {
      request.append('birthday', form.birthdate);
    }

    if (customGender) {
      if (form.isValidGender) {
        request.append('gender', form.gender);
      } else {
        setForm({...form, attemptedSubmit: false});
        setTimeout(() => setForm({...form, attemptedSubmit: true}));
        invalidFields = true;
      }
    } else {
      if (form.isValidGender) {
        request.append('gender', form.gender);
      }
    }

    if (form.classYear !== -1) {
      request.append('university_class', form.classYear);
    }

    if (invalidFields) {
      return;
    }

    const endpoint = EDIT_PROFILE_ENDPOINT + `${userId}/`;
    try {
      const token = await AsyncStorage.getItem('token');
      let response = await fetch(endpoint, {
        method: 'PATCH',
        headers: {
          'Content-Type': 'multipart/form-data',
          Authorization: 'Token ' + token,
        },
        body: request,
      });
      let statusCode = response.status;
      let data = await response.json();
      if (statusCode === 200) {
        navigation.navigate('SocialMedia', {
          userId: userId,
          username: username,
        });
      } else if (statusCode === 400) {
        Alert.alert(
          'Profile update failed. 😔',
          data.error || 'Something went wrong! 😭',
        );
      } else {
        Alert.alert(ERROR_SOMETHING_WENT_WRONG_REFRESH);
      }
    } catch (error) {
      Alert.alert(ERROR_PROFILE_CREATION_SHORT, ERROR_DOUBLE_CHECK_CONNECTION);
      return {
        name: 'Profile creation error',
        description: error,
      };
    }
  };

  return (
    <Animated.ScrollView bounces={false}>
      <Background
        centered
        gradientType={BackgroundGradientType.Light}
        style={styles.container}>
        <StatusBar barStyle="light-content" />
        <View style={styles.profile}>
          <LargeProfilePic />
          <SmallProfilePic />
        </View>
        <View style={styles.contentContainer}>
          <TaggInput
            accessibilityHint="Enter a website."
            accessibilityLabel="Website input field."
            placeholder="Website"
            autoCompleteType="off"
            textContentType="URL"
            autoCapitalize="none"
            returnKeyType="next"
            onChangeText={handleWebsiteUpdate}
            onSubmitEditing={() => handleFocusChange('bio')}
            blurOnSubmit={false}
            valid={form.isValidWebsite}
            attemptedSubmit={form.attemptedSubmit}
            invalidWarning={'Website must be a valid link to your website'}
            width={280}
          />
          <TaggBigInput
            accessibilityHint="Enter a bio."
            accessibilityLabel="Bio input field."
            placeholder="Bio"
            autoCompleteType="off"
            textContentType="none"
            autoCapitalize="none"
            returnKeyType="next"
            onChangeText={handleBioUpdate}
            onSubmitEditing={() => handleFocusChange('bio')}
            blurOnSubmit={false}
            ref={bioRef}
            valid={form.isValidBio}
            attemptedSubmit={form.attemptedSubmit}
            invalidWarning={
              'Bio must be less than 150 characters and must contain valid characters'
            }
            width={280}
          />
          <BirthDatePicker
            ref={birthdateRef}
            handleBDUpdate={handleBirthdateUpdate}
            width={280}
            date={form.birthdate}
            showPresetdate={false}
          />
          <TaggDropDown
            onValueChange={(value: string) => handleClassYearUpdate(value)}
            items={classYearList}
            placeholder={{
              label: 'Class Year',
              value: null,
              color: '#ddd',
            }}
          />
          {customGender && (
            <TaggInput
              accessibilityHint="Custom"
              accessibilityLabel="Gender input field."
              placeholder="Enter your gender"
              autoCompleteType="off"
              textContentType="none"
              autoCapitalize="none"
              returnKeyType="next"
              blurOnSubmit={false}
              ref={customGenderRef}
              onChangeText={handleCustomGenderUpdate}
              onSubmitEditing={() => handleSubmit()}
              valid={form.isValidGender}
              attemptedSubmit={form.attemptedSubmit}
              invalidWarning={
                'Custom field can only contain letters and hyphens'
              }
              width={280}
            />
          )}
          <TaggDropDown
            onValueChange={(value: string) => handleGenderUpdate(value)}
            items={[
              {label: 'Male', value: 'male'},
              {label: 'Female', value: 'female'},
              {label: 'Custom', value: 'custom'},
            ]}
            placeholder={{
              label: 'Gender',
              value: null,
              color: '#ddd',
            }}
          />
          <TouchableOpacity onPress={handleSubmit} style={styles.submitBtn}>
            <Text style={styles.submitBtnLabel}>Let's start!</Text>
          </TouchableOpacity>
        </View>
      </Background>
    </Animated.ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'space-around',
    marginBottom: '10%',
  },
  profile: {
    flexDirection: 'row',
    marginBottom: '5%',
  },
  contentContainer: {
    position: 'relative',
    width: 280,
    alignSelf: 'center',
  },
  largeProfileUploader: {
    justifyContent: 'center',
    alignItems: 'center',
    padding: 15,
    backgroundColor: '#fff',
    marginLeft: '13%',
    marginTop: '10%',
    height: 230,
    width: 230,
    borderRadius: 23,
  },
  largeProfileText: {
    textAlign: 'center',
    fontSize: 14,
    fontWeight: 'bold',
    color: '#863FF9',
  },
  largeProfilePic: {
    height: 230,
    width: 230,
    borderRadius: 23,
  },
  smallProfileUploader: {
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#E1F0FF',
    right: '18%',
    marginTop: '38%',
    height: 110,
    width: 110,
    borderRadius: 55,
  },
  smallProfileText: {
    textAlign: 'center',
    fontSize: 14,
    fontWeight: 'bold',
    color: '#806DF4',
  },
  smallProfilePic: {
    height: 110,
    width: 110,
    borderRadius: 55,
  },
  submitBtn: {
    backgroundColor: '#8F01FF',
    justifyContent: 'center',
    alignItems: 'center',
    width: SCREEN_WIDTH / 2.5,
    height: SCREEN_WIDTH / 10,
    borderRadius: 5,
    marginTop: '5%',
    alignSelf: 'center',
    marginBottom: SCREEN_WIDTH / 3,
  },
  submitBtnLabel: {
    fontSize: 16,
    fontWeight: '500',
    color: '#fff',
  },
});

export default ProfileOnboarding;
