import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import React, {FC, useEffect, useMemo, useState} from 'react';
import {
  Alert,
  Image,
  ImageSourcePropType,
  Keyboard,
  KeyboardAvoidingView,
  Platform,
  StyleSheet,
  Text,
  TouchableOpacity,
  TouchableWithoutFeedback,
  View,
} from 'react-native';
import {Button} from 'react-native-elements';
import Video from 'react-native-video';
import {useDispatch, useSelector} from 'react-redux';
import FrontArrow from '../../assets/icons/front-arrow.svg';
import {
  MentionInputControlled,
  SearchBackground,
  TaggSquareButton,
} from '../../components';
import {CaptionScreenHeader} from '../../components/';
import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator';
import {TAGG_LIGHT_BLUE_2} from '../../constants';
import {
  ERROR_NO_MOMENT_CATEGORY,
  ERROR_SOMETHING_WENT_WRONG_REFRESH,
  ERROR_UPLOAD,
  SUCCESS_PIC_UPLOAD,
} from '../../constants/strings';
import * as RootNavigation from '../../RootNavigation';
import {MainStackParams} from '../../routes';
import {
  handlePresignedURL,
  handleVideoUpload,
  patchMoment,
  postMoment,
  postMomentTags,
} from '../../services';
import {
  loadUserMoments,
  updateProfileCompletionStage,
} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
import {MomentTagType} from '../../types';
import {isIPhoneX, normalize, SCREEN_WIDTH, StatusBarHeight} from '../../utils';
import {mentionPartTypes} from '../../utils/comments';

/**
 * Upload Screen to allow users to upload posts to Tagg
 */
type CaptionScreenRouteProp = RouteProp<MainStackParams, 'CaptionScreen'>;

type CaptionScreenNavigationProp = StackNavigationProp<
  MainStackParams,
  'CaptionScreen'
>;

interface CaptionScreenProps {
  route: CaptionScreenRouteProp;
  navigation: CaptionScreenNavigationProp;
}

const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
  // moment is only present when editing
  const {moment} = route.params;
  const {
    user: {userId},
  } = useSelector((state: RootState) => state.user);
  const dispatch = useDispatch();
  const [caption, setCaption] = useState(moment ? moment.caption : '');
  const [loading, setLoading] = useState(false);
  const [tags, setTags] = useState<MomentTagType[]>([]);
  const [taggedUsersText, setTaggedUsersText] = useState('');
  const [momentCategory, setMomentCategory] = useState<string | undefined>();
  const mediaUri = moment ? moment.moment_url : route.params.media!.uri;
  // TODO: change this once moment refactor is done
  const isMediaAVideo = moment
    ? !(
        moment.moment_url.endsWith('.jpg') ||
        moment.moment_url.endsWith('.JPG') ||
        moment.moment_url.endsWith('.png') ||
        moment.moment_url.endsWith('.PNG')
      )
    : route.params.media?.isVideo ?? false;

  useEffect(() => {
    setTags(route.params.selectedTags ?? []);
  }, [route.params.selectedTags]);

  useEffect(() => {
    setMomentCategory(route.params.selectedCategory);
  }, [route.params.selectedCategory]);

  useEffect(() => {
    let listString = '';
    // Append non-truncated usernames together and no more than 21 characters total
    // e.g. "@ivan.tagg"
    // e.g. "@ivan.tagg @foobar . . ."
    for (const tag of tags) {
      const usernameStr = `@${tag.user.username} `;
      if (listString.length + usernameStr.length > 21) {
        listString = listString.concat('. . .');
        break;
      } else {
        listString = listString.concat(usernameStr);
      }
    }
    setTaggedUsersText(listString);
  }, [tags]);

  const handleFailed = (noCategory = false) => {
    setLoading(false);
    navigation.dangerouslyGetParent()?.setOptions({
      tabBarVisible: true,
    });
    setTimeout(() => {
      if (noCategory) {
        Alert.alert(ERROR_NO_MOMENT_CATEGORY);
      } else {
        Alert.alert(moment ? ERROR_SOMETHING_WENT_WRONG_REFRESH : ERROR_UPLOAD);
      }
    }, 500);
  };
  const handleSuccess = () => {
    setLoading(false);
    navigation.dangerouslyGetParent()?.setOptions({
      tabBarVisible: true,
    });
    if (!moment) {
      // if posting, pop all screens until at camera screen (default upload screen)
      // then switch to the profile tab
      navigation.popToTop();
      RootNavigation.navigate('ProfileTab');
      setTimeout(() => {
        if (isMediaAVideo) {
          Alert.alert(
            'Beautiful, the Moment was uploaded successfully! Check back in a bit and refresh to see it!',
          );
        } else {
          Alert.alert(SUCCESS_PIC_UPLOAD);
        }
      }, 500);
    } else {
      // if editing, simply go back to profile screen
      navigation.navigate('Profile', {
        userXId: undefined,
        screenType: route.params.screenType,
      });
    }
  };

  const formattedTags = () => {
    return tags.map((tag) => ({
      x: Math.floor(tag.x),
      y: Math.floor(tag.y),
      z: Math.floor(tag.z),
      user_id: tag.user.id,
    }));
  };

  const handleShare = async () => {
    setLoading(true);
    if (moment || !momentCategory) {
      handleFailed(true);
      return;
    }
    let profileCompletionStage;
    let momentId;
    // separate upload logic for image/video
    if (isMediaAVideo) {
      const presignedURLResponse = await handlePresignedURL(momentCategory);
      if (!presignedURLResponse) {
        handleFailed();
        return;
      }
      momentId = presignedURLResponse.moment_id;
      const fileHash = presignedURLResponse.response_url.fields.key;
      if (fileHash !== null && fileHash !== '' && fileHash !== undefined) {
        await handleVideoUpload(mediaUri, presignedURLResponse);
      } else {
        handleFailed();
      }
    } else {
      const momentResponse = await postMoment(
        mediaUri,
        caption,
        momentCategory,
        userId,
      );
      if (!momentResponse) {
        handleFailed();
        return;
      }
      profileCompletionStage = momentResponse.profile_completion_stage;
      momentId = momentResponse.moment_id;
    }
    if (momentId) {
      const momentTagResponse = await postMomentTags(momentId, formattedTags());
      if (!momentTagResponse) {
        handleFailed();
        return;
      }
    }
    if (!isMediaAVideo) {
      dispatch(loadUserMoments(userId));
    }
    if (profileCompletionStage) {
      dispatch(updateProfileCompletionStage(profileCompletionStage));
    }
    handleSuccess();
  };

  const handleSubmitEditChanges = async () => {
    setLoading(true);
    if (moment?.moment_id && momentCategory) {
      const success = await patchMoment(
        moment.moment_id,
        caption,
        momentCategory,
        formattedTags(),
      );
      if (success) {
        dispatch(loadUserMoments(userId));
        handleSuccess();
      } else {
        handleFailed();
      }
    }
  };

  const SelectableItem: FC<{
    text: 'Tag Friends' | 'Category';
    imageUri: ImageSourcePropType;
    onPress: () => void;
  }> = ({text, imageUri, onPress}) => {
    return (
      <TouchableOpacity
        onPress={onPress}
        style={styles.selectableItemContainer}>
        <View style={styles.row}>
          {text === 'Category' && !momentCategory && (
            <Text style={styles.asteriskText}>* </Text>
          )}
          <Image style={styles.tagIcon} source={imageUri} />
          <Text style={styles.selectableItemTitle}>{text}</Text>
        </View>
        <View style={styles.row}>
          {text === 'Tag Friends' && (
            <Text style={styles.itemInfoText}>{taggedUsersText}</Text>
          )}
          {text === 'Category' && (
            <Text style={styles.itemInfoText}>{momentCategory}</Text>
          )}
          <FrontArrow
            width={normalize(13)}
            height={normalize(13)}
            color={'white'}
          />
        </View>
      </TouchableOpacity>
    );
  };

  return (
    <SearchBackground>
      {loading && <TaggLoadingIndicator fullscreen />}
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <KeyboardAvoidingView
          behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
          keyboardVerticalOffset={isIPhoneX() ? 40 : 30}
          style={styles.flex}>
          <View style={styles.contentContainer}>
            <View style={styles.buttonsContainer}>
              <Button
                title="Cancel"
                buttonStyle={styles.button}
                onPress={() => navigation.goBack()}
              />
            </View>
            <CaptionScreenHeader style={styles.header} title={'Moments'} />
            <View style={styles.captionContainer}>
              {isMediaAVideo ? (
                <Video
                  style={styles.media}
                  source={{uri: mediaUri}}
                  repeat={true}
                />
              ) : (
                <Image
                  style={styles.media}
                  source={{uri: mediaUri}}
                  resizeMode={'contain'}
                />
              )}
              <MentionInputControlled
                style={styles.text}
                containerStyle={styles.flex}
                placeholder="Write something....."
                placeholderTextColor="white"
                value={caption}
                onChange={setCaption}
                partTypes={mentionPartTypes('white', 'caption', true)}
              />
            </View>
            {useMemo(
              () => (
                <SelectableItem
                  text={'Category'}
                  imageUri={require('../../assets/images/images.png')}
                  onPress={() =>
                    navigation.navigate('ChoosingCategoryScreen', {})
                  }
                />
              ),
              [momentCategory],
            )}
            {useMemo(
              () => (
                <SelectableItem
                  text={'Tag Friends'}
                  imageUri={require('../../assets/icons/tagging/tag-icon.png')}
                  onPress={() =>
                    navigation.navigate('TagFriendsScreen', {
                      media: {
                        uri: mediaUri,
                        isVideo: isMediaAVideo,
                      },
                      selectedTags: tags,
                    })
                  }
                />
              ),
              [taggedUsersText],
            )}
            {momentCategory ? (
              <TaggSquareButton
                onPress={moment ? handleSubmitEditChanges : handleShare}
                title={moment ? 'Update' : 'Post'}
                buttonStyle={'large'}
                buttonColor={'blue'}
                labelColor={'white'}
                style={styles.postButton}
                labelStyle={styles.postText}
              />
            ) : (
              <TaggSquareButton
                disabled={true}
                onPress={moment ? handleSubmitEditChanges : handleShare}
                title={moment ? 'Update' : 'Post'}
                buttonStyle={'large'}
                buttonColor={'blue'}
                labelColor={'white'}
                style={[styles.postButton, styles.greyBackground]}
                labelStyle={styles.postText}
              />
            )}
          </View>
        </KeyboardAvoidingView>
      </TouchableWithoutFeedback>
    </SearchBackground>
  );
};
const styles = StyleSheet.create({
  contentContainer: {
    paddingTop: StatusBarHeight,
    justifyContent: 'flex-end',
  },
  buttonsContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginLeft: '5%',
    marginRight: '5%',
  },
  button: {
    backgroundColor: 'transparent',
  },
  shareButtonTitle: {
    fontWeight: 'bold',
    color: TAGG_LIGHT_BLUE_2,
  },
  header: {
    marginTop: 20,
    marginBottom: 30,
  },
  captionContainer: {
    flexDirection: 'row',
    padding: normalize(15),
    marginBottom: normalize(35),
    borderColor: 'white',
    borderTopWidth: 1,
    borderBottomWidth: 1,
    zIndex: 1,
  },
  media: {
    height: normalize(150),
    aspectRatio: 9 / 16,
  },
  text: {
    color: 'white',
    fontSize: normalize(12),
    lineHeight: 14,
    fontWeight: '500',
    height: normalize(150),
    marginLeft: normalize(15),
  },
  flex: {
    flex: 1,
  },
  selectableItemTitle: {
    color: 'white',
    fontSize: normalize(14),
    lineHeight: normalize(16.71),
    letterSpacing: normalize(0.3),
    fontWeight: '600',
  },
  selectableItemContainer: {
    marginHorizontal: '5%',
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: normalize(42),
  },
  asteriskText: {
    color: TAGG_LIGHT_BLUE_2,
    fontWeight: 'bold',
    fontSize: normalize(15),
    height: 15,
    alignSelf: 'center',
  },
  itemInfoText: {
    color: 'white',
    width: 150,
    fontSize: normalize(10),
    lineHeight: normalize(11),
    letterSpacing: normalize(0.3),
    textAlign: 'right',

    marginRight: 5,
  },
  tagIcon: {
    width: normalize(20),
    height: normalize(20),
    marginRight: 15,
  },
  row: {
    flexDirection: 'row',
  },
  greyBackground: {
    backgroundColor: '#C4C4C4',
  },
  postButton: {
    width: SCREEN_WIDTH * 0.8,
    height: normalize(37),
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 6,
    alignSelf: 'center',
  },
  postText: {
    color: 'white',
    fontWeight: 'bold',
    fontSize: normalize(15),
    lineHeight: 18,
    letterSpacing: 2,
  },
});

export default CaptionScreen;
