'use client';

import { useStatsigClient } from '@statsig/react-bindings';
import { observer } from 'mobx-react-lite';
import { useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';
import { useIsClient } from 'usehooks-ts';

import { useStores } from '@/app/(root)/AppProviders';
import SongList from '@/components/song/Songlist';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import { components } from '@/lib/gen';
import { ContextType } from '@/logging/contextTypes';
import { QueryParams } from '@/state/searchStore';

import { Clip } from '../../../state/clipStore';
import SearchFilters from './SearchFilters';
import { PUBLIC_SONG, SEARCH_PAGE_SIZE } from './utils';

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

const SearchSongList = observer(() => {
  const { clips, search } = useStores();
  const [searching, setSearching] = useState(false);
  const [queryParams, setQueryParams] = useState<QueryParams>(
    new QueryParams({
      searchType: PUBLIC_SONG,
      query: '',
      isPublic: true,
      rankBy: 'default',
      fromIndex: 0,
      pageSize: SEARCH_PAGE_SIZE,
    })
  );
  const [isInstrumental, setIsInstrumental] = useState<boolean>(false);
  const [modelVersion, setModelVersion] = useState<string | undefined>(
    undefined
  );

  const handleFilterChange = (
    newIsInstrumental: boolean,
    newModelVersion?: string
  ) => {
    setIsInstrumental(newIsInstrumental);
    setModelVersion(newModelVersion);
  };

  const statsigClient = useStatsigClient();

  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(searchResult);
      clips.updateClips(searchResult.result as Clip[]);
    } 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: PUBLIC_SONG,
        query: search.searchTerm,
        isPublic: true,
        rankBy: search.searchRankingType,
        fromIndex: 0,
        pageSize: SEARCH_PAGE_SIZE,
        is_instrumental: isInstrumental,
        model_version: modelVersion,
      })
    );
    const searchingClips = async () => {
      await search.searchData(
        search.searchTerm,
        false,
        PUBLIC_SONG,
        search.searchRankingType,
        isInstrumental,
        modelVersion
      );
      setSearching(false);
    };
    searchingClips();
  }, [
    search.searchTerm,
    search.searchRankingType,
    isInstrumental,
    modelVersion,
  ]);

  const { ref: spinnerRef } = useInView({
    threshold: 0,
    onChange: async (inView) => {
      if (inView && searching === false) {
        const searchingClips = async () => {
          setSearching(true);
          await search.searchData(
            search.searchTerm,
            true,
            PUBLIC_SONG,
            search.searchRankingType,
            isInstrumental,
            modelVersion
          );
          clips.updateClips(searchResult?.result as Clip[]);
          setSearching(false);
        };
        searchingClips();
      }
    },
  });

  const isClient = useIsClient();

  if (!isClient) {
    return (
      <div className='flex h-full flex-row items-center justify-center pt-10'>
        <SpinnerSVG className='ml-3' />
      </div>
    );
  }

  return (
    <div className='sticky top-0 mb-5 flex w-full flex-1 flex-col gap-3 overflow-y-auto'>
      {statsigClient.checkGate('search-v4-instrumental-2025') && (
        <SearchFilters
          isInstrumental={isInstrumental}
          modelVersion={modelVersion}
          onFilterChange={handleFilterChange}
        />
      )}
      <div className='flex flex-col overflow-y-auto'>
        <div className='ml-6 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.length > 0
                    ? ` "${search.searchTerm}"`
                    : 'popular songs'
                }...`}
              </span>
              <SpinnerSVG className='ml-3' />
            </div>
          ) : searchResult?.result?.length ? (
            <span className='font-sans text-sm font-normal'>
              {search.searchTerm.length > 0
                ? `Search results for "${search.searchTerm}"`
                : 'Popular songs'}
            </span>
          ) : (
            <span className='font-sans text-sm font-normal'>
              No songs found.
            </span>
          )}
        </div>
        <SongList
          songs={searchResult.result as Clip[]}
          infiniteScrollLoadingRef={spinnerRef}
          playlistId={queryParams.getSearchCacheKey()}
          contextId={queryParams.getSearchCacheKey()}
          contextType={ContextType.Search}
          isLoading={searching}
          useNewSongRow={true}
          showPreview={false}
          songRowProps={{
            showModelTagOnly: true,
            showStats: true,
            showActions: true,
            showUser: true,
            isFromSongRow: false,
            stream: false,
            trendingMode: true,
          }}
        />
      </div>
    </div>
  );
});

export default SearchSongList;
