import styled from '@emotion/styled';
import { pick } from 'lodash-es';
import { useEffect, useState } from 'react';

import { useContextSelector } from '@/hooks/useContextSelector';
import useDebounceCallback from '@/hooks/useDebounceCallback';
import { useSearchInput } from '@/hooks/useSearchInput';
import {
  CoverCreateIcon,
  ExtendRightIcon,
  FilterIcon,
  FourStarIcon,
  GlobeIcon,
  PersonaCreateIcon,
  SearchIcon,
  SortIcon,
  StemsIcon,
  ThumbsDownIcon,
  ThumbsUpIcon,
  TriangleDownIcon,
  TriangleLeftIcon,
  TriangleRightIcon,
  UploadIcon,
  VinylIcon,
} from '@/icons';

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

const PaginationControls = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  margin-left: auto;
`;

const PageInput = styled.input`
  background-color: var(--color-background-primary);
  border: 1px solid var(--color-border-primary);
  border-radius: 100px;
  padding: 8px 12px;
  width: 54px;
  color: var(--color-foreground-primary);
  font-size: 12px;
  font-weight: 500;
  text-align: center;
  outline: none;

  &:focus {
    border-color: var(--color-accent-brand);
  }
`;

export default function WorkspaceFilters() {
  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 hideClipsFromEditMode = useContextSelector(
    ClipBrowserContext,
    (context) =>
      context.filters.fromStudioProject.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 extendOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.extend.presence === BooleanFilter.True
  );
  const fullSongOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.fullSong === BooleanFilter.True
  );
  const remasterOnly = useContextSelector(
    ClipBrowserContext,
    (context) => context.filters.remaster.presence === 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
  );

  // Pagination state
  const currentPageNumber = useContextSelector(
    ClipBrowserContext,
    (context) => context.currentPageNumber
  );
  const setPageNumber = useContextSelector(
    ClipBrowserContext,
    (context) => context.setPageNumber
  );

  const [localPageNumber, setLocalPageNumber] = useState(
    (currentPageNumber || 1).toString()
  );

  // Update local page number when currentPageNumber changes
  useEffect(() => {
    setLocalPageNumber((currentPageNumber || 1).toString());
  }, [currentPageNumber]);

  const filterCount = [
    likedOnly,
    publicOnly,
    uploadOnly,
    fullSongOnly,
    coverOnly,
    extendOnly,
    personaOnly,
    hideDisliked,
    hideStems,
    hideClipsFromEditMode,
    remasterOnly,
  ].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}>
      <SearchInputWrapper>
        <SearchIcon className='h-6 w-6' />
        <SearchInput
          {...searchInputProps}
          placeholder='Search'
          value={localSearchText}
          onChange={(e) => {
            setLocalSearchText(e.target.value);
            debouncedSetSearchText(e.target.value);
          }}
          aria-label='Search clips'
        />
      </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}
              icon={<ThumbsUpIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only liked clips'
            />
            <FilterMenuItem
              label='Public'
              onChange={() => setFilters(setPublicOnly(!publicOnly))}
              value={publicOnly}
              icon={<GlobeIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only public clips'
            />
            <FilterMenuItem
              label='Uploads'
              onChange={() => setFilters(setUploadOnly(!uploadOnly))}
              value={uploadOnly}
              icon={<UploadIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only uploaded clips'
            />
            <FilterMenuItem
              label='Full Songs'
              onChange={() => setFilters(setFullSongOnly(!fullSongOnly))}
              value={fullSongOnly}
              icon={<VinylIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only full songs'
            />
            <FilterMenuItem
              label='Covers'
              onChange={() => setFilters(setCoverOnly(!coverOnly))}
              value={coverOnly}
              icon={<CoverCreateIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only covers'
            />
            <FilterMenuItem
              label='Extensions'
              onChange={() => setFilters(setExtendOnly(!extendOnly))}
              value={extendOnly}
              icon={<ExtendRightIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only extensions'
            />
            <FilterMenuItem
              label='Personas'
              onChange={() => setFilters(setPersonaOnly(!personaOnly))}
              value={personaOnly}
              icon={<PersonaCreateIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only personas'
            />
            <FilterMenuItem
              label='Remasters'
              onChange={() => setFilters(setRemasterOnly(!remasterOnly))}
              value={remasterOnly}
              icon={<FourStarIcon className='h-4 w-4' />}
              ariaLabel='Filter to show only remasters'
            />
            <FilterMenuItem
              label='Hide Disliked'
              onChange={() => setFilters(setHideDisliked(!hideDisliked))}
              value={hideDisliked}
              icon={<ThumbsDownIcon className='h-4 w-4' />}
              ariaLabel='Hide disliked clips'
            />
            <FilterMenuItem
              label='Hide Stems'
              onChange={() => setFilters(setHideStems(!hideStems))}
              value={hideStems}
              icon={<StemsIcon className='h-4 w-4' />}
              ariaLabel='Hide stems'
            />
            <FilterMenuItem
              label='Hide Clips from Edit Mode'
              onChange={() =>
                setFilters(setHideClipsFromEditMode(!hideClipsFromEditMode))
              }
              value={hideClipsFromEditMode}
              icon={<StemsIcon className='h-4 w-4' />}
              ariaLabel='Hide clips from edit mode'
            />
          </>
        )}
      />
      <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))}
          aria-label='Filter to show only liked clips'
        >
          Liked
        </FilterButton>
      </ResponsiveChild>
      <ResponsiveChild hideBelowWidth={900} containerName={containerName}>
        <FilterButton
          active={publicOnly}
          onClick={() => setFilters(setPublicOnly(!publicOnly))}
          aria-label='Filter to show only public clips'
        >
          Public
        </FilterButton>
      </ResponsiveChild>
      <ResponsiveChild hideBelowWidth={900} containerName={containerName}>
        <FilterButton
          active={uploadOnly}
          onClick={() => setFilters(setUploadOnly(!uploadOnly))}
          aria-label='Filter to show only uploaded clips'
        >
          Uploads
        </FilterButton>
      </ResponsiveChild>
      <PaginationControls>
        <Button
          variant={ButtonVariant.Standard}
          shape={ButtonShape.Pill}
          onClick={() =>
            setPageNumber(Math.max(1, (currentPageNumber || 1) - 1))
          }
          disabled={(currentPageNumber || 1) <= 1}
          icon={<TriangleLeftIcon className='h-4 w-4' />}
          className='p-2.5 text-xs'
          aria-label='Previous page'
        />
        <PageInput
          value={localPageNumber}
          onChange={(e) => {
            const value = e.target.value.replace(/[^0-9]/g, '');
            setLocalPageNumber(value);
          }}
          onKeyDown={(e) => {
            if (e.key === 'Enter') {
              const page = parseInt(e.currentTarget.value);
              if (!isNaN(page) && page > 0) {
                setPageNumber(page);
              } else {
                setLocalPageNumber((currentPageNumber || 1).toString());
              }
              e.currentTarget.blur();
            }
          }}
          onBlur={(e) => {
            const page = parseInt(e.target.value);
            if (!isNaN(page) && page > 0) {
              setPageNumber(page);
            } else {
              setLocalPageNumber((currentPageNumber || 1).toString());
            }
          }}
          aria-label='Current page number'
        />
        <Button
          variant={ButtonVariant.Standard}
          shape={ButtonShape.Pill}
          onClick={() => setPageNumber((currentPageNumber || 1) + 1)}
          icon={<TriangleRightIcon className='h-4 w-4' />}
          className='p-2.5 text-xs'
          aria-label='Next page'
        />
      </PaginationControls>
    </FilterSectionWrapper>
  );
}
