import AsyncStorage from '@react-native-community/async-storage';
import {useFocusEffect, useNavigation} from '@react-navigation/native';
import moment from 'moment';
import React, {useCallback, useEffect, useState} from 'react';
import {
  Alert,
  Image,
  Linking,
  RefreshControl,
  SectionList,
  StatusBar,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import {checkPermission} from 'react-native-contacts';
import {TouchableOpacity} from 'react-native-gesture-handler';
import {SafeAreaView} from 'react-native-safe-area-context';
import {useDispatch, useSelector} from 'react-redux';
import FindFriendsBlueIcon from '../../assets/icons/findFriends/find-friends-blue-icon.svg';
import {TabsGradient} from '../../components';
import {Notification} from '../../components/notifications';
import {NewChatPrompt} from '../../components/notifications/NotificationPrompts';
import {
  loadUserNotifications,
  updateNewNotificationReceived,
} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
import {NotificationType, ScreenType} from '../../types';
import {getDateAge, normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
import EmptyContentView from '../../components/common/EmptyContentView';

const NotificationsScreen: React.FC = () => {
  const {newNotificationReceived} = useSelector(
    (state: RootState) => state.user,
  );
  const [refreshing, setRefreshing] = useState(false);
  // used for figuring out which ones are unread
  const [lastViewed, setLastViewed] = useState<moment.Moment | undefined>(
    undefined,
  );
  const {notifications} = useSelector(
    (state: RootState) => state.notifications,
  );
  const {suggested_people_linked} = useSelector(
    (state: RootState) => state.user.profile,
  );
  const [showSPNotifyPopUp, setShowSPNotifyPopUp] = useState(false);
  const {user: loggedInUser} = useSelector((state: RootState) => state.user);
  const [sectionedNotifications, setSectionedNotifications] = useState<
    {
      title: 'Friend Requests' | 'Today' | 'Yesterday' | 'This Week';
      data: NotificationType[];
    }[]
  >([]);

  const DEFAULT_NOTIFICATIONS_SIZE = 2;

  const [footerEnabled, setFooterEnabled] = useState(false);
  const [requestLimit, setRequestLimit] = useState(DEFAULT_NOTIFICATIONS_SIZE);
  const [allFriendRequests, setFriendRequests] = useState<NotificationType[]>(
    [],
  );

  const dispatch = useDispatch();

  const refreshNotifications = () => {
    const refrestState = async () => {
      dispatch(loadUserNotifications());
    };
    setRefreshing(true);
    refrestState().then(() => {
      setRefreshing(false);
    });
  };

  const onRefresh = useCallback(() => {
    refreshNotifications();
  }, [refreshNotifications]);

  useEffect(() => {
    setShowSPNotifyPopUp(suggested_people_linked !== 2);
  }, [suggested_people_linked]);

  useFocusEffect(
    useCallback(() => {
      const resetNewNotificationFlag = () => {
        if (newNotificationReceived) {
          dispatch(updateNewNotificationReceived(false));
        }
      };

      //Called everytime screen is focused
      if (newNotificationReceived) {
        refreshNotifications();
      }

      //Called when user leaves the screen
      return () => resetNewNotificationFlag();
    }, [newNotificationReceived, dispatch, refreshNotifications]),
  );

  // handles storing and fetching the "previously viewed" information
  useEffect(() => {
    const getAndUpdateLastViewed = async () => {
      const key = 'notificationLastViewed';
      const previousLastViewed = await AsyncStorage.getItem(key);
      setLastViewed(
        previousLastViewed == null
          ? moment.unix(0)
          : moment(previousLastViewed),
      );
      await AsyncStorage.setItem(key, moment().toString());
    };
    getAndUpdateLastViewed();
  }, [notifications]);

  // handles sectioning notifications to "date age"
  // mark notifications as read or unread
  useEffect(() => {
    const sortedNotifications = (notifications ?? [])
      .slice()
      .sort((a, b) => (a.timestamp < b.timestamp ? 1 : -1));
    let todays = [];
    let yesterdays = [];
    let thisWeeks = [];
    let friendRequests = [];
    for (const n of sortedNotifications) {
      const notificationDate = moment(n.timestamp);
      const dateAge = getDateAge(notificationDate);
      if (dateAge === 'unknown') {
        continue;
      }
      const unread = lastViewed ? lastViewed.diff(notificationDate) < 0 : false;
      const newN = {...n, unread};

      if (n.notification_type === 'FRD_REQ') {
        friendRequests.push(newN);
      } else {
        switch (dateAge) {
          case 'today':
            todays.push(newN);
            continue;
          case 'yesterday':
            yesterdays.push(newN);
            continue;
          case 'thisWeek':
            thisWeeks.push(newN);
            continue;
          default:
            continue;
        }
      }
    }
    setFriendRequests(friendRequests);
    setFooterEnabled(
      requestLimit === friendRequests.length &&
        friendRequests.length > DEFAULT_NOTIFICATIONS_SIZE,
    );
    setSectionedNotifications(
      todays.length === 0 &&
        yesterdays.length === 0 &&
        thisWeeks.length === 0 &&
        friendRequests.length === 0
        ? []
        : [
            {
              title: 'Friend Requests',
              data: friendRequests.slice(0, requestLimit),
            },
            {title: 'Today', data: todays},
            {title: 'Yesterday', data: yesterdays},
            {title: 'This Week', data: thisWeeks},
          ],
    );
  }, [lastViewed, notifications, showSPNotifyPopUp, requestLimit]);

  const renderNotification = ({item}: {item: NotificationType}) => (
    <Notification
      item={item}
      screenType={ScreenType.Notifications}
      loggedInUser={loggedInUser}
    />
  );

  const renderSectionHeader = ({
    section: {title, data},
  }: {
    section: {title: string; data: NotificationType[]};
  }) =>
    data.length !== 0 && (
      <View style={styles.sectionHeaderContainer}>
        <Text
          style={[
            styles.sectionFont,
            styles.sectionHeader,
            styles.sectionLocation,
          ]}>
          {title}
        </Text>
      </View>
    );

  const renderSectionFooter = ({
    section: {title},
  }: {
    section: {title: string};
  }) => {
    if (title === 'Friend Requests') {
      if (footerEnabled) {
        return (
          <TouchableOpacity
            style={styles.sectionHeaderContainer}
            onPress={() => {
              setRequestLimit(DEFAULT_NOTIFICATIONS_SIZE);
            }}>
            <View
              style={[styles.sectionLocation, styles.hiddenSectionContainer]}>
              <Image
                style={styles.hideImageStyles}
                source={require('../../assets/images/hide-caret.png')}
              />
              <Text style={[styles.sectionFont, styles.sectionFooter]}>
                {'Hide'}
              </Text>
            </View>
          </TouchableOpacity>
        );
      }

      if (allFriendRequests.length > DEFAULT_NOTIFICATIONS_SIZE) {
        return (
          <TouchableOpacity
            style={styles.sectionHeaderContainer}
            onPress={() => {
              setRequestLimit(allFriendRequests.length);
            }}>
            <Text
              style={[
                styles.sectionFont,
                styles.sectionFooter,
                styles.sectionLocation,
              ]}>
              {`+ ${allFriendRequests.length - requestLimit} More`}
            </Text>
          </TouchableOpacity>
        );
      }
    }

    return null;
  };

  const navigation = useNavigation();

  const InviteFriends = () => (
    <TouchableOpacity
      style={styles.findFriendsButton}
      onPress={async () => {
        const permission = await checkPermission();
        if (permission === 'authorized') {
          navigation.navigate('InviteFriendsScreen', {
            screenType: ScreenType.Profile,
          });
        } else {
          Alert.alert(
            '"Tagg" Would Like to Access Your Contacts',
            'This helps you quickly get in touch with friends on the app and more',
            [
              {
                text: "Don't Allow",
                style: 'cancel',
              },
              {text: 'Allow', onPress: () => Linking.openSettings()},
            ],
          );
        }
      }}>
      <FindFriendsBlueIcon width={18} height={18} />
      <Text style={styles.findFriendsSubheaderText}>Invite Friends</Text>
    </TouchableOpacity>
  );

  return (
    <View style={styles.background}>
      <SafeAreaView>
        <StatusBar barStyle="dark-content" />
        <View style={styles.header}>
          <Text style={styles.headerText}>Notifications</Text>
          <InviteFriends />
        </View>
        <SectionList
          contentContainerStyle={styles.container}
          stickySectionHeadersEnabled={false}
          sections={sectionedNotifications}
          keyExtractor={(_item, index) => index.toString()}
          renderItem={renderNotification}
          renderSectionHeader={renderSectionHeader}
          renderSectionFooter={renderSectionFooter}
          ListHeaderComponent={<NewChatPrompt />}
          refreshControl={
            <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
          }
          extraData={requestLimit}
          ListEmptyComponent={
            <View style={styles.emptyViewContainer}>
              <EmptyContentView viewType={'Notification'} />
            </View>
          }
        />
      </SafeAreaView>
      <TabsGradient />
    </View>
  );
};

const styles = StyleSheet.create({
  background: {
    width: SCREEN_WIDTH,
    height: SCREEN_HEIGHT,
    backgroundColor: 'white',
  },
  header: {
    marginLeft: '8%',
    marginTop: '5%',
    alignSelf: 'flex-start',
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'space-between',
    width: SCREEN_WIDTH * 0.9,
  },
  headerText: {
    fontWeight: '700',
    fontSize: normalize(18),
    lineHeight: normalize(21),
  },
  container: {
    paddingBottom: '20%',
    minHeight: (SCREEN_HEIGHT * 8) / 10,
  },
  sectionHeaderContainer: {
    width: '100%',
    backgroundColor: 'white',
  },

  sectionLocation: {
    marginLeft: '8%',
    marginTop: '5%',
    marginBottom: '2%',
  },

  sectionFont: {
    fontWeight: '600',
    fontSize: normalize(12),
    lineHeight: normalize(14),
  },
  hiddenSectionContainer: {
    flexDirection: 'row',
  },
  hideImageStyles: {alignSelf: 'center', marginRight: 8},
  sectionHeader: {
    color: '#828282',
  },
  sectionFooter: {
    color: '#698DD3',
  },
  emptyViewContainer: {
    flex: 1,
    justifyContent: 'center',
  },
  findFriendsButton: {
    flexDirection: 'row',
    height: 14,
    marginTop: '5%',
  },
  findFriendsSubheaderText: {
    marginLeft: '5%',
    color: '#08E2E2',
    fontSize: normalize(12),
    fontWeight: '600',
    lineHeight: normalize(14.32),
  },
});

export default NotificationsScreen;
