import { observer } from 'mobx-react-lite';
import { useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';

import { useStores } from '@/app/(root)/AppProviders';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import { components } from '@/lib/gen';
import { QueryParams } from '@/state/searchStore';
import { SEARCH_OPTION_TRENDING } from '@/utils/constants';

import UserCard from './UserCard';
import { USER, USER_SEARCH_PAGE_SIZE } from './utils';

export type SearchResult = components['schemas']['BaseSearchResult'];

const Users = observer<any>(() => {
  const { search } = useStores();
  const [searching, setSearching] = useState(false);

  const [queryParams, setQueryParams] = useState<QueryParams>(
    new QueryParams({
      searchType: USER,
      query: '',
      isPublic: true,
      rankBy: SEARCH_OPTION_TRENDING,
      fromIndex: 0,
      pageSize: USER_SEARCH_PAGE_SIZE,
    })
  );
  const [searchResult, setSearchResult] = useState<any>([]);
  useEffect(() => {
    const searchRes =
      search.searchResultCache[queryParams?.getSearchCacheKey()];
    if (searchRes) {
      setSearchResult(
        search.searchResultCache[queryParams?.getSearchCacheKey()]
      );
    } else {
      setSearchResult({
        total_hits: 0,
        result: [],
        from_index: 0,
        page_size: USER_SEARCH_PAGE_SIZE,
      });
    }
  }, [search.searchResultCache[queryParams?.getSearchCacheKey()]]);

  useEffect(() => {
    setSearching(true);
    setQueryParams(
      new QueryParams({
        searchType: USER,
        query: search.searchTerm,
        isPublic: true,
        rankBy: SEARCH_OPTION_TRENDING,
        fromIndex: 0,
        pageSize: USER_SEARCH_PAGE_SIZE,
      })
    );
    const searchingUsers = async () => {
      await search.searchData(
        search.searchTerm,
        false,
        USER,
        SEARCH_OPTION_TRENDING,
        undefined,
        undefined,
        USER_SEARCH_PAGE_SIZE
      );
      setSearching(false);
    };
    searchingUsers();
  }, [search.searchTerm]);

  const { ref: spinnerRef } = useInView({
    threshold: 0,
    onChange: async (inView) => {
      // if total results <= 20, don't increment
      if (inView && searching === false && searchResult.total_hits > 20) {
        setSearching(true);
        await search.searchData(
          search.searchTerm,
          true,
          USER,
          SEARCH_OPTION_TRENDING,
          undefined,
          undefined,
          USER_SEARCH_PAGE_SIZE
        );
        setSearching(false);
      }
    },
  });

  return (
    <div className='sticky mx-6 overflow-y-auto'>
      <div className='pb-2 text-xl font-bold'>
        {searching ? (
          <div className='flex flex-row items-center'>
            <span className='font-sans text-xl font-bold'>
              {'Searching ' + search.searchTerm}
            </span>
            <SpinnerSVG className='ml-3' />
          </div>
        ) : searchResult?.total_hits > 0 ? (
          <span>
            {search.searchTerm.length > 0
              ? `Search results for "${search.searchTerm}"`
              : 'Popular Users:'}
          </span>
        ) : (
          <span>{'No users found.'}</span>
        )}
      </div>

      <div className='relative flex w-full flex-row flex-wrap gap-4 lg:gap-8'>
        {searchResult?.result?.map((user: any, key: number) => (
          <UserCard
            key={key}
            display_name={user.display_name}
            avatar_image_url={user.avatar_image_url}
            handle={user.handle}
            followers_count={user.stats.followers_count}
          />
        ))}
        <div
          className='relative flex h-[224px] w-64 flex-col items-center justify-center gap-4 p-4'
          ref={spinnerRef}
        >
          {searching && <SpinnerSVG />}
        </div>
      </div>
    </div>
  );
});
export default Users;
