import AsyncStorage from '@react-native-community/async-storage';
import {useFocusEffect} from '@react-navigation/native';
import React, {useCallback, useEffect, useState} from 'react';
import {
  Keyboard,
  RefreshControl,
  ScrollView,
  StatusBar,
  StyleSheet,
} from 'react-native';
import Animated, {Easing, timing} from 'react-native-reanimated';
import {useDispatch, useSelector} from 'react-redux';
import {
  Explore,
  RecentSearches,
  SearchBackground,
  SearchBar,
  SearchHeader,
  SearchResultList,
  SearchResultsBackground,
  TabsGradient,
} from '../../components';
import {SEARCH_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants';
import {loadSearchResults} from '../../services';
import {loadRecentlySearched, resetScreenType} from '../../store/actions';
import {RootState} from '../../store/rootReducer';
import {ProfilePreviewType, ScreenType} from '../../types';
import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils';

/**
 * Search Screen for user recommendations and a search
 * tool to allow user to find other users
 */

const SearchScreen: React.FC = () => {
  const {recentSearches} = useSelector((state: RootState) => state.taggUsers);
  const [query, setQuery] = useState<string>('');
  const [results, setResults] = useState<Array<any> | undefined>(undefined);
  const [recents, setRecents] = useState<Array<ProfilePreviewType>>(
    recentSearches ?? [],
  );
  const [searching, setSearching] = useState(false);
  const top = Animated.useValue(-SCREEN_HEIGHT);
  const [refreshing, setRefreshing] = useState<boolean>(false);
  const [keyboardVisible, setKeyboardVisible] = React.useState(
    'keyboardVisible',
  );
  useEffect(() => {
    const showKeyboard = () => setKeyboardVisible('keyboardVisibleTrue');
    Keyboard.addListener('keyboardWillShow', showKeyboard);
    return () => Keyboard.removeListener('keyboardWillShow', showKeyboard);
  }, []);

  useEffect(() => {
    const hideKeyboard = () => setKeyboardVisible('keyboardVisibleFalse');
    Keyboard.addListener('keyboardWillHide', hideKeyboard);
    return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard);
  }, []);
  const dispatch = useDispatch();

  const onRefresh = useCallback(() => {
    const refrestState = async () => {
      dispatch(loadRecentlySearched());
    };
    setRefreshing(true);
    refrestState().then(() => {
      setRefreshing(false);
    });
  }, []);

  useEffect(() => {
    if (query.length < 3) {
      setResults(undefined);
      return;
    }
    (async () => {
      const searchResults = await loadSearchResults(
        `${SEARCH_ENDPOINT}?query=${query}`,
      );
      if (query.length > 2) {
        const categories = searchResults?.categories;
        const users = searchResults?.users;
        const sanitizedResult = [
          {
            title: 'categories',
            data: categories,
          },
          {
            title: 'users',
            data: users,
          },
        ];
        setResults(sanitizedResult);
      } else {
        setResults(undefined);
      }
    })();
  }, [query]);

  /**
   * Code under useFocusEffect gets executed every time the screen comes under focus / is being viewed by the user.
   * This is done to reset the users stored in our store for the Search screen.
   * Read more here : https://reactnavigation.org/docs/function-after-focusing-screen/
   */
  useFocusEffect(() => {
    dispatch(resetScreenType(ScreenType.Search));
  });

  const handleFocus = () => {
    const topInConfig = {
      duration: 180,
      toValue: 0,
      easing: Easing.bezier(0.31, 0.14, 0.66, 0.82),
    };
    timing(top, topInConfig).start();
    setSearching(true);
  };
  const handleBlur = () => {
    setQuery('');
    Keyboard.dismiss();
    const topOutConfig = {
      duration: 180,
      toValue: -SCREEN_HEIGHT,
      easing: Easing.inOut(Easing.ease),
    };
    timing(top, topOutConfig).start();
    setSearching(false);
  };
  const loadRecentlySearchedUsers = async () => {
    try {
      const asyncCache = await AsyncStorage.getItem('@recently_searched_users');
      asyncCache != null ? setRecents(JSON.parse(asyncCache)) : setRecents([]);
    } catch (e) {
      console.log(e);
    }
  };
  const clearRecentlySearched = async () => {
    try {
      await AsyncStorage.removeItem('@recently_searched_users');
      loadRecentlySearchedUsers();
    } catch (e) {
      console.log(e);
    }
  };
  const handleUpdate = async (val: string) => {
    setQuery(val);
    loadRecentlySearchedUsers();
  };

  return (
    <SearchBackground>
      <StatusBar barStyle="dark-content" />
      <ScrollView
        scrollEnabled={!searching}
        keyboardShouldPersistTaps={'always'}
        stickyHeaderIndices={[4]}
        contentContainerStyle={styles.contentContainer}
        showsVerticalScrollIndicator={false}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }>
        <SearchHeader style={styles.header} {...{top}} />
        <SearchBar
          style={styles.searchBar}
          onCancel={handleBlur}
          onChangeText={handleUpdate}
          onBlur={Keyboard.dismiss}
          onFocus={handleFocus}
          value={query}
          {...{top, searching}}
        />
        <Explore />

        <SearchResultsBackground {...{top}}>
          {results === undefined && recents.length !== 0 ? (
            <RecentSearches
              sectionTitle="Recent"
              sectionButtonTitle="Clear all"
              onPress={clearRecentlySearched}
              recents={recents}
              screenType={ScreenType.Search}
            />
          ) : (
            <SearchResultList
              {...{results}}
              keyboardVisible={keyboardVisible === 'keyboardVisibleTrue'}
              previewType={'Search'}
              screenType={ScreenType.Search}
            />
          )}
        </SearchResultsBackground>
      </ScrollView>
      <TabsGradient />
    </SearchBackground>
  );
};

const styles = StyleSheet.create({
  contentContainer: {
    paddingTop: StatusBarHeight,
    paddingBottom: SCREEN_HEIGHT / 15,
  },
  searchBar: {
    paddingHorizontal: '3%',
  },
  header: {
    marginVertical: 20,
    zIndex: 1,
  },
  recentsHeaderContainer: {
    flexDirection: 'row',
  },
  recentsHeader: {
    fontSize: 17,
    fontWeight: 'bold',
    flexGrow: 1,
  },
  clear: {
    fontSize: 17,
    fontWeight: 'bold',
    color: TAGG_LIGHT_BLUE,
  },
  image: {
    width: SCREEN_WIDTH,
    height: SCREEN_WIDTH,
  },
  textContainer: {
    marginTop: '10%',
  },
  headerText: {
    color: '#fff',
    fontSize: 32,
    fontWeight: '600',
    textAlign: 'center',
    marginBottom: '4%',
    marginHorizontal: '10%',
  },
  subtext: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
    textAlign: 'center',
    marginHorizontal: '10%',
  },
});
export default SearchScreen;
