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

import { queryParamStorage } from 'features/QueryParamsStorage'

import {
  dateReplacer,
  readStorageInitialValue,
} from './helpers'

type Args<T> = {
  defaultValue: T,
  key: string,

  /**
   * функция для валидации полученного значения из стора
   * если значение не валидно то используется defaultValue
   */
  validator?: (value: T) => boolean,
}

/**
 * Хук высшего порядка, получает сторедж
 * и возвращает хук работающий с данным стореджем
 * Хук считывает значение из стора и использует как начальное значение стейта,
 * при вызове сеттера обновляется сторедж и реакт стейет
 */
const createHook = (storage: Storage) => (
  <T extends any>({
    defaultValue,
    key,
    validator,
  }: Args<T>) => {
    const storeValue = readStorageInitialValue(storage, key)
    const isValid = validator && validator(storeValue)
    const initialState = isValid ? storeValue : defaultValue

    const [state, setState] = useState<T>(initialState)

    const setStateAndSave = useCallback((value: T) => {
      storage.setItem(key, JSON.stringify(value, dateReplacer))
      setState(value)
    }, [key])

    useEffect(() => {
      if (!isValid) {
        storage.removeItem(key)
      }
    }, [isValid, key])

    return [state, setStateAndSave] as const
  }
)

export const useLocalStore = createHook(localStorage)
export const useSessionStore = createHook(sessionStorage)
export const useQueryParamStore = createHook(queryParamStorage)
