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

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

import { PLAYLIST, SEARCH_PAGE_SIZE } from './utils';

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

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

  const [queryParams, setQueryParams] = useState<QueryParams>(
    new QueryParams({
      searchType: PLAYLIST,
      query: '',
      isPublic: true,
      rankBy: 'default',
      fromIndex: 0,
      pageSize: SEARCH_PAGE_SIZE,
    })
  );
  const [searchResult, setSearchResult] = useState<SearchResult>({
    total_hits: 0,
    result: [] as any,
    from_index: 0,
    page_size: SEARCH_PAGE_SIZE,
  } as any);

  useEffect(() => {
    const searchResult =
      search.searchResultCache[queryParams?.getSearchCacheKey()];
    if (searchResult) {
      setSearchResult(
        search.searchResultCache[queryParams?.getSearchCacheKey()]
      );
    } else {
      setSearchResult({
        total_hits: 0,
        result: [],
        from_index: 0,
        page_size: SEARCH_PAGE_SIZE,
      });
    }
  }, [search.searchResultCache[queryParams?.getSearchCacheKey()]]);

  useEffect(() => {
    setSearching(true);
    setQueryParams(
      new QueryParams({
        searchType: PLAYLIST,
        query: search.searchTerm,
        isPublic: true,
        rankBy: search.searchRankingType,
        fromIndex: 0,
        pageSize: SEARCH_PAGE_SIZE,
      })
    );
    const searchingPlaylist = async () => {
      await search.searchData(
        search.searchTerm,
        false,
        PLAYLIST,
        search.searchRankingType
      );
      setSearching(false);
    };
    searchingPlaylist();
  }, [search.searchTerm, search.searchRankingType]);

  const { ref: spinnerRef } = useInView({
    threshold: 0,
    onChange: async (inView) => {
      if (inView && searching === false) {
        setSearching(true);
        await search.searchData(
          search.searchTerm,
          true,
          PLAYLIST,
          search.searchRankingType
        );
        setSearching(false);
      }
    },
  });

  return (
    <div
      className='sticky mr-5 ml-6 flex flex-col overflow-y-auto'
      style={{ scrollbarWidth: 'none' }}
    >
      <div className='pb-2'>
        {searching ? (
          <div className='flex flex-row items-center'>
            <span className='font-sans text-xl font-bold'>
              {`Searching ${search.searchTerm.length > 0 ? ` "${search.searchTerm}"` : 'popular playlists'}...`}
            </span>
            <SpinnerSVG className='ml-3' />
          </div>
        ) : searchResult?.result?.length ? (
          <span className='font-sans text-xl font-bold'>
            {search.searchTerm.length > 0
              ? `Search results for "${search.searchTerm}"`
              : 'Popular playlists'}
          </span>
        ) : (
          <span className='font-sans text-xl font-bold'>
            {'No playlists found.'}
          </span>
        )}
      </div>
      <motion.div className='flex flex-1 flex-col overflow-y-auto'>
        <div className='grid grid-cols-2 gap-6 md:grid-cols-3 lg:grid-cols-4'>
          {searchResult?.result?.map((playlist: any) => (
            <PlaylistCard
              key={playlist.id}
              playlist={playlist}
              showPlaylistStats
            />
          ))}
          <div ref={spinnerRef} />
        </div>
      </motion.div>
    </div>
  );
});
export default Playlist;
