import { useState } from 'react';
import { useWixPatternsRouter } from '../providers/WixPatternsRouterProvider';
import { ICollectionComponentState } from '../state/ICollectionComponentState';
import { getCollectionComponentUniqueId } from '../utils/getCollectionComponentUniqueId';
import {
  CollectionState,
  QueryCache,
  WixPatternsContainer,
} from '@wix/bex-core';
import { useSyncCollectionOnEntityCreate } from './useSyncCollectionOnEntityCreate';
import { useSyncCollectionOnEntityUpdate } from './useSyncCollectionOnEntityUpdate';
import { WixPatternsRouterState } from '../state/WixPatternsRouterState';
import { useWixPatternsContainer } from '@wix/bex-core/react';

export interface IUseOptionalCachedStateOptions<
  S extends ICollectionComponentState,
> {
  getCollectionsToUpdate?: (
    state: S,
    entity: any,
  ) => CollectionState<any>[] | null;
  shouldResetCache?: ({
    router,
    uniqueId,
  }: {
    router: WixPatternsRouterState | null;
    uniqueId: string;
  }) => boolean;
}

const getCachedState = <S extends ICollectionComponentState>({
  shouldResetCache,
  uniqueId,
  router,
  container,
}: {
  shouldResetCache?: ({
    router,
    uniqueId,
  }: {
    router: WixPatternsRouterState | null;
    uniqueId: string;
  }) => boolean;
  uniqueId: string;
  router: WixPatternsRouterState | null;
  container: WixPatternsContainer;
}) => {
  const resetCache = shouldResetCache?.({
    router,
    uniqueId,
  });

  if (resetCache) {
    router?.stateRefs.delete(uniqueId);
    container.queryCache = new QueryCache();
  }
  return router?.stateRefs.get(uniqueId) as S | undefined;
};

export function useOptionalCachedState<S extends ICollectionComponentState>(
  createState: () => S,
  {
    getCollectionsToUpdate,
    shouldResetCache,
  }: IUseOptionalCachedStateOptions<S> = {},
): S {
  const container = useWixPatternsContainer();
  const router = useWixPatternsRouter();
  const [maybeNewState] = useState<S>(() => createState());
  const uniqueId = getCollectionComponentUniqueId(maybeNewState);

  const [cachedState] = useState<S | undefined>(
    getCachedState<S>({ router, uniqueId, shouldResetCache, container }),
  );

  useSyncCollectionOnEntityCreate(cachedState, getCollectionsToUpdate);
  useSyncCollectionOnEntityUpdate(cachedState, getCollectionsToUpdate);

  const [state] = useState<S>(() => {
    if (router) {
      router.isUsingCache = !!cachedState;
    }

    if (cachedState) {
      return cachedState;
    }

    router?.saveState<S>(maybeNewState);
    return maybeNewState;
  });

  return state;
}
