import AsyncStorage from '@react-native-community/async-storage';
import {useFocusEffect} from '@react-navigation/native';
import moment from 'moment';
import React, {useCallback, useEffect, useState} from 'react';
import {
  RefreshControl,
  SectionList,
  StatusBar,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {useDispatch, useSelector} from 'react-redux';
import {Notification} from '../../components/notifications';
import {
  loadUserNotifications,
  updateNewNotificationReceived,
} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
import {NotificationType, ScreenType} from '../../types';
import {getDateAge, SCREEN_HEIGHT} from '../../utils';

const NotificationsScreen: React.FC = () => {
  const {moments: loggedInUserMoments} = useSelector(
    (state: RootState) => state.moments,
  );
  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 {user: loggedInUser} = useSelector((state: RootState) => state.user);

  const [sectionedNotifications, setSectionedNotifications] = useState<
    {title: 'Today' | 'Yesterday' | 'This Week'; data: NotificationType[]}[]
  >([]);

  const dispatch = useDispatch();

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

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

  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 = [];
    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};
      switch (dateAge) {
        case 'today':
          todays.push(newN);
          continue;
        case 'yesterday':
          yesterdays.push(newN);
          continue;
        case 'thisWeek':
          thisWeeks.push(newN);
          continue;
        default:
          continue;
      }
    }
    setSectionedNotifications([
      {title: 'Today', data: todays},
      {title: 'Yesterday', data: yesterdays},
      {title: 'This Week', data: thisWeeks},
    ]);
  }, [lastViewed, notifications]);

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

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

  return (
    <SafeAreaView>
      <StatusBar barStyle={'dark-content'} />
      <View style={styles.header}>
        <Text style={styles.headerText}>Notifications</Text>
        <View style={styles.underline} />
      </View>
      <SectionList
        contentContainerStyle={styles.container}
        sections={sectionedNotifications}
        keyExtractor={(item, index) => index.toString()}
        renderItem={renderNotification}
        renderSectionHeader={renderSectionHeader}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  header: {
    marginLeft: '8%',
    marginTop: '5%',
    alignSelf: 'flex-start',
    flexDirection: 'column',
  },
  headerText: {
    fontWeight: 'bold',
    fontSize: 16,
  },
  underline: {
    borderWidth: 2,
    borderColor: '#8F01FF',
  },
  container: {
    paddingBottom: '20%',
    minHeight: (SCREEN_HEIGHT * 8) / 10,
  },
  sectionHeaderContainer: {
    width: '100%',
    backgroundColor: '#f3f2f2',
  },
  sectionHeader: {
    marginLeft: '8%',
    marginTop: '5%',
    marginBottom: '2%',
    fontSize: 15,
  },
});

export default NotificationsScreen;
