import {useCallback, useEffect, useState} from 'react'

import debounce from 'lodash/debounce'

import {useShopActionInfiniteQuery} from '../../internal/reactQuery'
import {useShopActions} from '../../internal/useShopActions'
import {
  PaginatedDataHookOptionsBase,
  PaginatedDataHookReturnsBase,
  Product,
  ProductFilters,
  ProductSearchSortBy,
} from '../../types'

export interface UseProductSearchParams extends PaginatedDataHookOptionsBase {
  /**
   * The search query.
   */
  query: string
  /**
   * The filters to apply to the search.
   */
  filters?: ProductFilters
  /**
   * The sort order of the results.
   */
  sortBy?: ProductSearchSortBy
  /**
   * Whether to include sensitive products.
   */
  includeSensitive?: boolean
}

interface UseProductSearchReturns extends PaginatedDataHookReturnsBase {
  /**
   * The products returned from the query.
   */
  products: Product[] | null
  /**
   * Whether the user is typing.
   */
  isTyping: boolean
}

export const useProductSearch = (
  params: UseProductSearchParams
): UseProductSearchReturns => {
  const {getProductSearch} = useShopActions()
  const {
    query,
    filters,
    sortBy,
    includeSensitive = false,
    skip = false,
    ...restParams
  } = params ?? {}

  const [debouncedQuery, setDebouncedQuery] = useState<string>(query)

  // eslint-disable-next-line react-hooks/exhaustive-deps
  const debouncedSetQuery = useCallback(
    debounce((newQuery: string) => {
      setDebouncedQuery(prev => {
        // Only update if the query actually changed
        if (prev === newQuery) return prev
        return newQuery
      })
    }, 300),
    []
  )

  useEffect(() => {
    debouncedSetQuery(query)

    return () => {
      debouncedSetQuery.cancel()
    }
  }, [query, debouncedSetQuery])

  // Use our Shop Action infinite query helper
  const {data, ...rest} = useShopActionInfiniteQuery(
    [
      'productSearch',
      debouncedQuery,
      filters,
      sortBy,
      includeSensitive,
      restParams,
    ],
    getProductSearch,
    {
      query: debouncedQuery,
      filters,
      sortBy,
      includeSensitive,
      ...restParams,
    },
    {
      skip: skip || debouncedQuery.trim().length === 0,
    }
  )

  return {
    ...rest,
    products: data,
    isTyping: debouncedQuery !== query,
  }
}
