import React, {Fragment, useCallback, useEffect, useState} from 'react';
import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import {
  Text,
  StatusBar,
  StyleSheet,
  Image,
  TouchableOpacity,
  Alert,
  View,
  SafeAreaView,
  KeyboardAvoidingView,
  Platform,
  Keyboard,
} from 'react-native';
import {Button} from 'react-native-elements';
import {
  Background,
  TaggBigInput,
  TaggInput,
  TaggDropDown,
  TabsGradient,
  SocialIcon,
} from '../../components';
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 {MainStackParams} from '../../routes';
import Animated from 'react-native-reanimated';
import {HeaderHeight, SCREEN_HEIGHT} from '../../utils';
import {RootState} from '../../store/rootReducer';
import {useDispatch, useSelector} from 'react-redux';
import {loadUserData} from '../../store/actions';
import {BackgroundGradientType, ScreenType} from '../../types';
import {
  ERROR_DOUBLE_CHECK_CONNECTION,
  ERROR_SOMETHING_WENT_WRONG_REFRESH,
  ERROR_UPLOAD_LARGE_PROFILE_PIC,
  ERROR_UPLOAD_SMALL_PROFILE_PIC,
} from '../../constants/strings';
import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator';

type EditProfileNavigationProp = StackNavigationProp<
  MainStackParams,
  'EditProfile'
>;

interface EditProfileProps {
  route: RouteProp<MainStackParams, 'EditProfile'>;
  navigation: EditProfileNavigationProp;
}

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

const EditProfile: React.FC<EditProfileProps> = ({route, navigation}) => {
  const y: Animated.Value<number> = Animated.useValue(0);
  const {userId, username} = route.params;
  const {
    profile: {website, biography, gender, snapchat, tiktok, university_class},
    avatar,
    cover,
  } = useSelector((state: RootState) => state.user);

  const [needsUpdate, setNeedsUpdate] = useState(false);
  const [loading, setLoading] = useState(false);
  const dispatch = useDispatch();

  useEffect(() => {
    if (needsUpdate) {
      dispatch(loadUserData({userId, username}));
    }
  }, [dispatch, needsUpdate, userId, username]);

  const [isCustomGender, setIsCustomGender] = React.useState<boolean>(
    gender !== '' && gender !== 'female' && gender !== 'male',
  );

  const [form, setForm] = React.useState({
    largePic: cover ? cover : '',
    smallPic: avatar ? avatar : '',
    website: website ? website : '',
    bio: biography ? biography : '',
    gender: isCustomGender ? 'custom' : gender,
    customGenderText: isCustomGender ? gender : '',
    snapchat: snapchat,
    tiktok: tiktok,
    isValidWebsite: true,
    isValidBio: true,
    isValidGender: true,
    isValidSnapchat: true,
    isValidTiktok: true,
    attemptedSubmit: false,
    classYear: university_class,
  });

  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') {
      setForm({...form, gender});
      setIsCustomGender(true);
    } else if (gender === null) {
      // not doing anything will make the picker "bounce back"
    } else {
      setIsCustomGender(false);
      let isValidGender: boolean = true;
      setForm({
        ...form,
        gender,
        isValidGender,
      });
    }
  };

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

  const handleSnapchatUpdate = (newUsername: string) => {
    // Allow any username, empty means to "un-link" it
    // TODO: refresh taggs bar after
    setForm({
      ...form,
      snapchat: newUsername,
    });
  };

  const handleTikTokUpdate = (newUsername: string) => {
    // Allow any username, empty means to "un-link" it
    // TODO: refresh taggs bar after
    setForm({
      ...form,
      tiktok: newUsername,
    });
  };

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

  const handleSubmit = useCallback(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.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.trim());
      } else {
        setForm({...form, attemptedSubmit: false});
        setTimeout(() => setForm({...form, attemptedSubmit: true}));
        invalidFields = true;
      }
    }

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

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

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

    if (form.classYear !== university_class) {
      if (!form.classYear) {
        invalidFields = true;
        Alert.alert('Please select a valid class year');
      } else {
        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) {
        setNeedsUpdate(true);
        navigation.pop();
      } 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_DOUBLE_CHECK_CONNECTION);
      return {
        name: 'Profile creation error',
        description: error,
      };
    }
  }, [isCustomGender, form, navigation, userId]);

  React.useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <Button
          title={'Save'}
          buttonStyle={{backgroundColor: 'transparent'}}
          titleStyle={{fontWeight: 'bold'}}
          onPress={() => {
            setLoading(true);
            handleSubmit().then(() => setLoading(false));
          }}
        />
      ),
    });
  }, [navigation, handleSubmit]);

  return (
    <Background centered gradientType={BackgroundGradientType.Light}>
      {loading ? <TaggLoadingIndicator fullscreen /> : <Fragment />}
      <SafeAreaView>
        <KeyboardAvoidingView
          behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
          <Animated.ScrollView
            style={styles.container}
            onScroll={(e) => y.setValue(e.nativeEvent.contentOffset.y)}
            showsHorizontalScrollIndicator={false}
            showsVerticalScrollIndicator={false}
            scrollEventThrottle={1}
            alwaysBounceVertical
            contentContainerStyle={{paddingBottom: SCREEN_HEIGHT / 15}}>
            <StatusBar barStyle="light-content" translucent={false} />
            <View
              style={{
                position: 'relative',
                alignSelf: 'center',
              }}>
              <View>
                <View style={styles.profile}>
                  <LargeProfilePic />
                  <SmallProfilePic />
                </View>
                <View
                  style={{
                    position: 'relative',
                    width: 280,
                    alignSelf: 'center',
                  }}>
                  <TaggInput
                    accessibilityHint="Enter a website."
                    accessibilityLabel="Website input field."
                    placeholder="Website"
                    autoCompleteType="off"
                    textContentType="URL"
                    autoCapitalize="none"
                    returnKeyType="done"
                    onChangeText={handleWebsiteUpdate}
                    blurOnSubmit={false}
                    valid={form.isValidWebsite}
                    attemptedSubmit={form.attemptedSubmit}
                    invalidWarning={
                      'Website must be a valid link to your website'
                    }
                    value={form.website}
                  />
                  <TaggBigInput
                    accessibilityHint="Enter a bio."
                    accessibilityLabel="Bio input field."
                    placeholder="Bio"
                    autoCompleteType="off"
                    textContentType="none"
                    autoCapitalize="none"
                    returnKeyType="next"
                    onChangeText={handleBioUpdate}
                    blurOnSubmit={false}
                    valid={form.isValidBio}
                    attemptedSubmit={form.attemptedSubmit}
                    invalidWarning={'Bio must be less than 150 characters'}
                    width={280}
                    value={form.bio}
                  />

                  <TaggDropDown
                    value={form.gender}
                    onValueChange={(value: string) => handleGenderUpdate(value)}
                    items={[
                      {label: 'Male', value: 'male'},
                      {label: 'Female', value: 'female'},
                      {label: 'Custom', value: 'custom'},
                    ]}
                    placeholder={{
                      label: 'Gender',
                      value: null,
                      color: '#fff',
                    }}
                  />
                  {isCustomGender && (
                    <TaggInput
                      accessibilityHint="Custom"
                      accessibilityLabel="Gender input field."
                      attemptedSubmit={form.attemptedSubmit}
                      autoCapitalize="none"
                      autoCompleteType="off"
                      blurOnSubmit={false}
                      invalidWarning={
                        'Custom field can only contain letters and hyphens'
                      }
                      onChangeText={handleCustomGenderUpdate}
                      placeholder="Enter your gender"
                      returnKeyType="done"
                      style={styles.customGenderInput}
                      textContentType="none"
                      valid={form.isValidGender}
                      value={form.customGenderText}
                    />
                  )}

                  <TaggDropDown
                    value={form.classYear.toString()}
                    onValueChange={(value: string) =>
                      handleClassYearUpdate(value)
                    }
                    items={classYearList}
                    placeholder={{
                      label: 'Class Year',
                      value: null,
                      color: '#ddd',
                    }}
                  />
                  {snapchat !== '' && (
                    <View style={styles.row}>
                      <SocialIcon
                        social={'Snapchat'}
                        style={styles.icon}
                        screenType={ScreenType.Profile}
                      />
                      <View style={styles.taggInput}>
                        <TaggInput
                          accessibilityHint="Snapchat Username"
                          accessibilityLabel="Snapchat Username Input Field."
                          attemptedSubmit={form.attemptedSubmit}
                          autoCapitalize="none"
                          autoCompleteType="off"
                          autoCorrect={false}
                          blurOnSubmit={false}
                          enablesReturnKeyAutomatically={true}
                          invalidWarning={'Please enter something!'}
                          onChangeText={handleSnapchatUpdate}
                          onSubmitEditing={Keyboard.dismiss}
                          placeholder="Username"
                          returnKeyType="done"
                          textContentType="none"
                          valid={form.isValidSnapchat}
                          value={form.snapchat && form.snapchat}
                        />
                      </View>
                    </View>
                  )}
                  {tiktok !== '' && (
                    <View style={styles.row}>
                      <SocialIcon
                        social={'TikTok'}
                        style={styles.icon}
                        screenType={ScreenType.Profile}
                      />
                      <View style={styles.taggInput}>
                        <TaggInput
                          accessibilityHint="TikTok Username"
                          accessibilityLabel="TikTok Username Input Field."
                          attemptedSubmit={form.attemptedSubmit}
                          autoCapitalize="none"
                          autoCompleteType="off"
                          autoCorrect={false}
                          blurOnSubmit={false}
                          enablesReturnKeyAutomatically={true}
                          invalidWarning={'Please enter something!'}
                          onChangeText={handleTikTokUpdate}
                          onSubmitEditing={Keyboard.dismiss}
                          placeholder="Username"
                          returnKeyType="done"
                          textContentType="none"
                          valid={form.isValidTiktok}
                          value={form.tiktok}
                        />
                      </View>
                    </View>
                  )}
                </View>
              </View>
            </View>
          </Animated.ScrollView>
        </KeyboardAvoidingView>
      </SafeAreaView>
      <TabsGradient />
    </Background>
  );
};

const styles = StyleSheet.create({
  container: {
    marginTop: HeaderHeight,
    flex: 1,
    flexDirection: 'column',
    width: '100%',
  },
  profile: {
    flexDirection: 'row',
    marginBottom: '5%',
    justifyContent: 'flex-end',
  },
  largeProfileUploader: {
    justifyContent: 'center',
    alignItems: 'center',
    padding: 15,
    backgroundColor: '#fff',
    marginLeft: '13%',
    marginTop: '5%',
    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: 150,
    height: 40,
    borderRadius: 5,
    marginTop: '5%',
  },
  submitBtnLabel: {
    fontSize: 16,
    fontWeight: '500',
    color: '#fff',
  },
  customGenderInput: {
    width: '100%',
    height: 40,
    fontSize: 16,
    fontWeight: '600',
    color: '#fff',
    borderColor: '#fffdfd',
    borderWidth: 2,
    borderRadius: 20,
    paddingLeft: 13,
  },
  row: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  icon: {
    aspectRatio: 1,
    flex: 1,
  },
  taggInput: {flex: 6.5, marginLeft: '3%'},
});

export default EditProfile;
