import AsyncStorage from '@react-native-community/async-storage';
import {useFocusEffect} from '@react-navigation/native';
import moment from 'moment';
import React, {
  Fragment,
  ReactElement,
  useCallback,
  useEffect,
  useState,
} from 'react';
import {
  Image,
  RefreshControl,
  SectionList,
  StatusBar,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {useDispatch, useSelector} from 'react-redux';
import {TabsGradient, TaggPrompt} from '../../components';
import {Notification} from '../../components/notifications';
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 EmptyNotificationView from './notification/EmptyNotificationView';

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: '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]);

  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 = [];
    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(
      todays.length === 0 && yesterdays.length === 0 && thisWeeks.length === 0
        ? []
        : [
            {title: 'Today', data: todays},
            {title: 'Yesterday', data: yesterdays},
            {title: 'This Week', data: thisWeeks},
          ],
    );
  }, [lastViewed, notifications, showSPNotifyPopUp]);

  useEffect(() => {
    console.log(sectionedNotifications);
  }, [sectionedNotifications]);

  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>
    );

  const SPPromptNotification: ReactElement = showSPNotifyPopUp ? (
    <TaggPrompt
      messageHeader={'New Suggested People Page!'}
      messageBody={
        <>
          <Text>
            A new page where you can discover new profiles. Just press the new{' '}
          </Text>
          <Image
            style={styles.icon}
            source={require('../../assets/navigationIcons/home.png')}
          />
          <Text> button on the tab bar to check it out!</Text>
        </>
      }
      logoType={'tagg'}
      hideCloseButton={true}
      noPadding={true}
      onClose={() => {}}
    />
  ) : (
    <Fragment />
  );

  return (
    <View style={styles.background}>
      <SafeAreaView>
        <StatusBar barStyle="dark-content" />
        <View style={styles.header}>
          <Text style={styles.headerText}>Notifications</Text>
        </View>
        <SectionList
          contentContainerStyle={styles.container}
          sections={sectionedNotifications}
          keyExtractor={(item, index) => index.toString()}
          renderItem={renderNotification}
          renderSectionHeader={renderSectionHeader}
          ListHeaderComponent={SPPromptNotification}
          refreshControl={
            <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
          }
          ListEmptyComponent={
            <View style={styles.emptyViewContainer}>
              <EmptyNotificationView />
            </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: 'column',
  },
  headerText: {
    fontWeight: '700',
    fontSize: normalize(18),
    lineHeight: normalize(21),
  },
  container: {
    paddingBottom: '20%',
    minHeight: (SCREEN_HEIGHT * 8) / 10,
  },
  sectionHeaderContainer: {
    width: '100%',
  },
  sectionHeader: {
    marginLeft: '8%',
    marginTop: '5%',
    marginBottom: '2%',
    fontWeight: '600',
    fontSize: normalize(12),
    lineHeight: normalize(14),
    color: '#828282',
  },
  emptyViewContainer: {
    flex: 1,
    justifyContent: 'center',
  },
  icon: {
    width: 20,
    height: 20,
    tintColor: 'grey',
  },
});

export default NotificationsScreen;
