import { pick } from 'lodash-es';

import { useContextSelector } from '@/hooks/useContextSelector';
import useDebounceCallback from '@/hooks/useDebounceCallback';
import { useSearchInput } from '@/hooks/useSearchInput';
import { FilterIcon, SearchIcon, SortIcon, TriangleDownIcon } from '@/icons';

import { ResponsiveChild, useContainer } from '../containerQueries/components';
import { ContextMenuTrigger } from '../contextMenu/ContextMenu';
import {
  FilterButton,
  FilterDropdownButton,
  FilterMenuItem,
  FilterSectionWrapper,
  SearchInput,
  SearchInputWrapper,
  SortMenuItem,
} from './FilterElements';
import {
  setCoverOnly,
  setFullSongOnly,
  setHideDisliked,
  setHideStems,
  setLikedOnly,
  setPersonaOnly,
  setPublicOnly,
  setSearchText,
  setSort,
  setUploadOnly,
} from './filterActions';
import { BooleanFilter, sortOptions } from './types';
import { ClipBrowserContext } from './useClipBrowser';

export default function LibraryFilters() {
  const likedOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.liked === BooleanFilter.True
  );
  const publicOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.public === BooleanFilter.True
  );
  const uploadOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.upload === BooleanFilter.True
  );
  const hideDisliked = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.disliked === BooleanFilter.False
  );
  const hideStems = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.stem.presence === BooleanFilter.False
  );
  const personaOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.persona.presence === BooleanFilter.True
  );
  const coverOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.cover.presence === BooleanFilter.True
  );
  const fullSongOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.fullSong === BooleanFilter.True
  );
  const sort = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.sort
  );
  const searchText = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.searchText
  );
  const setFilters = useContextSelector(
    ClipBrowserContext,
    (context) => context.setFilters
  );

  const filterCount = [
    likedOnly,
    publicOnly,
    uploadOnly,
    fullSongOnly,
    coverOnly,
    personaOnly,
    hideDisliked,
    hideStems,
  ].filter(Boolean).length;

  const { localSearchText, setLocalSearchText, searchInputProps } =
    useSearchInput(searchText);

  const debouncedSetSearchText = useDebounceCallback(
    (value: string) => setFilters(setSearchText(value)),
    150
  );

  const { containerRef, containerName } = useContainer();

  return (
    <FilterSectionWrapper ref={containerRef} style={{ marginTop: 16 }}>
      <SearchInputWrapper>
        <SearchIcon className='h-6 w-6' />
        <SearchInput
          {...searchInputProps}
          placeholder='Search'
          value={localSearchText}
          onChange={(e) => {
            setLocalSearchText(e.target.value);
            debouncedSetSearchText(e.target.value);
          }}
        />
      </SearchInputWrapper>
      <ContextMenuTrigger
        ButtonComponent={(props) => (
          <FilterDropdownButton icon={FilterIcon} {...props}>
            Filters {filterCount > 0 && `(${filterCount})`}
            <TriangleDownIcon className='-mx-1 h-5 w-5' />
          </FilterDropdownButton>
        )}
        ContentsComponent={() => (
          <>
            <FilterMenuItem
              label='Liked'
              onChange={() => setFilters(setLikedOnly(!likedOnly))}
              value={likedOnly}
            />
            <FilterMenuItem
              label='Public'
              onChange={() => setFilters(setPublicOnly(!publicOnly))}
              value={publicOnly}
            />
            <FilterMenuItem
              label='Uploads'
              onChange={() => setFilters(setUploadOnly(!uploadOnly))}
              value={uploadOnly}
            />
            <FilterMenuItem
              label='Full song'
              onChange={() => setFilters(setFullSongOnly(!fullSongOnly))}
              value={fullSongOnly}
            />
            <FilterMenuItem
              label='Cover'
              onChange={() => setFilters(setCoverOnly(!coverOnly))}
              value={coverOnly}
            />
            <FilterMenuItem
              label='Persona'
              onChange={() => setFilters(setPersonaOnly(!personaOnly))}
              value={personaOnly}
            />
            <FilterMenuItem
              label='Hide Disliked'
              onChange={() => setFilters(setHideDisliked(!hideDisliked))}
              value={hideDisliked}
            />
            <FilterMenuItem
              label='Hide Stems'
              onChange={() => setFilters(setHideStems(!hideStems))}
              value={hideStems}
            />
          </>
        )}
      />
      <ContextMenuTrigger
        ButtonComponent={(props) => (
          <FilterDropdownButton icon={SortIcon} {...props}>
            {sortOptions.find(
              (option) =>
                option.sortBy === sort.sortBy &&
                option.sortDirection === sort.sortDirection
            )?.label || 'Sort'}
            <TriangleDownIcon className='-mx-1 h-5 w-5' />
          </FilterDropdownButton>
        )}
        ContentsComponent={() => (
          <>
            {sortOptions.map((option) => (
              <SortMenuItem
                key={option.label}
                label={option.label}
                onActivate={() =>
                  setFilters(setSort(pick(option, 'sortBy', 'sortDirection')))
                }
                active={
                  sort.sortBy === option.sortBy &&
                  sort.sortDirection === option.sortDirection
                }
              />
            ))}
          </>
        )}
      />
      <ResponsiveChild hideBelowWidth={900} containerName={containerName}>
        <FilterButton
          className=''
          active={likedOnly}
          onClick={() => setFilters(setLikedOnly(!likedOnly))}
        >
          Liked
        </FilterButton>
      </ResponsiveChild>
      <ResponsiveChild hideBelowWidth={900} containerName={containerName}>
        <FilterButton
          active={publicOnly}
          onClick={() => setFilters(setPublicOnly(!publicOnly))}
        >
          Public
        </FilterButton>
      </ResponsiveChild>
      <ResponsiveChild hideBelowWidth={900} containerName={containerName}>
        <FilterButton
          active={uploadOnly}
          onClick={() => setFilters(setUploadOnly(!uploadOnly))}
        >
          Uploads
        </FilterButton>
      </ResponsiveChild>
    </FilterSectionWrapper>
  );
}
