import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
import React, {Fragment, useEffect, useState} from 'react';
import {
  Alert,
  Image,
  Keyboard,
  KeyboardAvoidingView,
  Platform,
  StyleSheet,
  Text,
  TouchableOpacity,
  TouchableWithoutFeedback,
  View,
} from 'react-native';
import {MentionInputControlled} from '../../components';
import {Button, normalize} 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 {SearchBackground} from '../../components';
import {CaptionScreenHeader} from '../../components/';
import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator';
import {TAGG_LIGHT_BLUE_2} from '../../constants';
import {
  ERROR_SOMETHING_WENT_WRONG_REFRESH,
  ERROR_UPLOAD,
  SUCCESS_PIC_UPLOAD,
} from '../../constants/strings';
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 {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}) => {
  const {title, screenType, selectedTags, 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[]>(
    selectedTags ? selectedTags : [],
  );
  const [taggedList, setTaggedList] = useState<string>('');
  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(selectedTags ? selectedTags : []);
  }, [selectedTags]);

  useEffect(() => {
    const getTaggedUsersListString = () => {
      let listString = '';
      for (let i = 0; i < tags.length; i++) {
        if (listString.length < 21) {
          listString = listString.concat(`@${tags[i].user.username} `);
        } else {
          break;
        }
      }
      setTaggedList(listString);
    };
    getTaggedUsersListString();
  }, [tags]);

  const navigateToProfile = () => {
    //Since the logged In User is navigating to own profile, useXId is not required
    navigation.navigate('Profile', {
      screenType,
      userXId: undefined,
    });
  };

  const handleFailed = () => {
    setLoading(false);
    setTimeout(() => {
      Alert.alert(moment ? ERROR_SOMETHING_WENT_WRONG_REFRESH : ERROR_UPLOAD);
    }, 500);
  };
  const handleSuccess = () => {
    setLoading(false);
    if (moment) {
      setLoading(false);
      navigation.goBack();
    } else {
      navigateToProfile();
      setTimeout(() => {
        Alert.alert(SUCCESS_PIC_UPLOAD);
      }, 500);
    }
  };

  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 || !title) {
      handleFailed();
      return;
    }
    let profileCompletionStage;
    let momentId;
    // separate upload logic for image/video
    if (isMediaAVideo) {
      const presignedURLResponse = await handlePresignedURL(title);
      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, title, 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;
      }
    }
    dispatch(loadUserMoments(userId));
    if (profileCompletionStage) {
      dispatch(updateProfileCompletionStage(profileCompletionStage));
    }
    handleSuccess();
  };

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

  return (
    <SearchBackground>
      {loading ? <TaggLoadingIndicator fullscreen /> : <Fragment />}
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <KeyboardAvoidingView
          behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
          style={styles.flex}>
          <View style={styles.contentContainer}>
            <View style={styles.buttonsContainer}>
              <Button
                title="Cancel"
                buttonStyle={styles.button}
                onPress={() =>
                  moment ? navigation.goBack() : navigateToProfile()
                }
              />
              <Button
                title={moment ? 'Done' : 'Share'}
                titleStyle={styles.shareButtonTitle}
                buttonStyle={styles.button}
                onPress={moment ? handleDoneEditing : handleShare}
              />
            </View>
            <CaptionScreenHeader
              style={styles.header}
              {...{title: moment ? moment.moment_category : title ?? ''}}
            />
            {isMediaAVideo ? (
              <Video
                style={styles.media}
                source={{uri: mediaUri}}
                repeat={true}
              />
            ) : (
              <Image
                style={styles.media}
                source={{uri: mediaUri}}
                resizeMode={'contain'}
              />
            )}
            <MentionInputControlled
              containerStyle={styles.text}
              placeholder="Write something....."
              placeholderTextColor="gray"
              value={caption}
              onChange={setCaption}
              partTypes={mentionPartTypes('blue', 'caption')}
            />
            <TouchableOpacity
              onPress={() =>
                navigation.navigate('TagFriendsScreen', {
                  media: {
                    uri: mediaUri,
                    isVideo: isMediaAVideo,
                  },
                  selectedTags: tags,
                })
              }
              style={styles.tagFriendsContainer}>
              <Image
                source={require('../../assets/icons/tagging/tag-icon.png')}
                style={styles.tagIcon}
              />
              <Text style={styles.tagFriendsTitle}>Tag Friends</Text>
              <Text numberOfLines={1} style={styles.taggedListContainer}>
                {taggedList}
                {taggedList.length > 21 ? '. . .' : ''}
              </Text>
              <FrontArrow width={12} height={12} color={'white'} />
            </TouchableOpacity>
          </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: {
    marginVertical: 20,
  },
  media: {
    position: 'relative',
    width: SCREEN_WIDTH,
    aspectRatio: 1,
    marginBottom: '3%',
  },
  text: {
    position: 'relative',
    backgroundColor: 'white',
    width: '100%',
    paddingHorizontal: '2%',
    paddingVertical: '1%',
    height: 60,
  },
  flex: {
    flex: 1,
  },
  tagFriendsTitle: {
    color: 'white',
    fontSize: normalize(12),
    lineHeight: normalize(16.71),
    letterSpacing: normalize(0.3),
    fontWeight: '600',
  },
  tagFriendsContainer: {
    marginHorizontal: '5%',
    marginTop: '3%',
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  taggedListContainer: {
    color: 'white',
    width: 150,
    fontSize: normalize(10),
    lineHeight: normalize(11),
    letterSpacing: normalize(0.3),
    textAlign: 'right',
  },
  tagIcon: {width: 20, height: 20},
});

export default CaptionScreen;
