import { useEffect, useMemo, useRef, useState } from 'react';
import { useWixPatternsRouter } from '../providers/WixPatternsRouterProvider';
import { ICollectionComponentState } from '../state/ICollectionComponentState';
import { useWixPatternsContainer } from '@wix/bex-core/react';
import { CollectionState, RemoveToast } from '@wix/bex-core';
import { useSelector } from '../useSelector';

export function useSyncCollectionOnEntityReturn<
  T,
  S extends ICollectionComponentState,
>({
  cachedState,
  updateCollection,
  checkIfViewSynced,
  getEntityFromRouterState,
  getCollectionsToUpdate,
}: {
  cachedState?: S;
  updateCollection: (collectionToUpdate: CollectionState<T>, entity: T) => void;
  checkIfViewSynced: (
    collectionToUpdate: CollectionState<T>,
    entity: T,
  ) => Promise<boolean>;
  getEntityFromRouterState: (state: {
    _updatedEntity?: T;
    _createdEntity?: T;
  }) => T | undefined;
  getCollectionsToUpdate?: (state: S, entity: T) => CollectionState<T>[] | null;
}) {
  const container = useWixPatternsContainer();
  const router = useWixPatternsRouter();
  const timeoutRef = useRef<number>();

  const routeState = useSelector(() => router?.currentState);

  const entity = useMemo(
    () => (routeState ? getEntityFromRouterState(routeState) : null),
    [getEntityFromRouterState, routeState],
  );
  const collections = useMemo(() => {
    if (!cachedState) {
      return null;
    }
    if (!entity) {
      return [cachedState.toolbar.collection];
    }

    return (
      getCollectionsToUpdate?.(cachedState, entity) || [
        cachedState.toolbar.collection,
      ]
    );
  }, [cachedState, entity]);

  const [currentToast, setCurrentToast] = useState<{
    remove: RemoveToast;
  } | null>(null);

  const showViewUpdatedToast = () => {
    const toast = container.showToast?.({
      type: 'STANDARD',
      timeout: 'NONE',
      message: container.translate(
        'cairo.updatedView.collectionPage.toast.desc',
      ),
      onCloseClick: () => {
        setCurrentToast(null);
      },
      biName: 'cairo-collection-page-updated-toast',
      action: {
        text: container.translate('cairo.updatedView.collectionPage.toast.cta'),
        onClick: () => {
          collections?.forEach((collection) =>
            collection.clearResultAndMoveToStart({ force: true }),
          );
          setCurrentToast(null);
        },
      },
    });

    if (toast) {
      setCurrentToast(toast);
    }
  };

  useEffect(() => {
    if (entity && collections && router) {
      collections.forEach((collection) => {
        updateCollection(collection, entity);
      });

      const timeoutId = window.setTimeout(() => {
        Promise.all(
          collections.map((collection) =>
            checkIfViewSynced(collection, entity),
          ),
        ).then((results) => {
          const isViewSynced =
            results.some(Boolean) && !router.isCollectionStale;
          if (!isViewSynced) {
            router.isCollectionStale = true;
            showViewUpdatedToast();
          }
        });
      }, 3000);

      timeoutRef.current = timeoutId;
    } else if (router?.isCollectionStale) {
      showViewUpdatedToast();
    }
  }, [collections, entity]);

  useEffect(() => {
    if (!currentToast || !cachedState) {
      return () => {};
    }

    const removeToast = () => {
      currentToast?.remove();
      setCurrentToast(null);
    };

    const onFetch = () => {
      removeToast();
      if (router) {
        router.isUsingCache = false;
        router.isCollectionStale = false;
      }
    };

    collections?.forEach((collection) => {
      collection?.emitter.on('fetch', () => {
        onFetch();
      });
    });
    return () => {
      collections?.forEach((collection) => {
        collection?.emitter.off('fetch', () => {
          onFetch();
        });
      });
    };
  }, [currentToast, collections]);

  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        window.clearTimeout(timeoutRef.current);
      }

      currentToast?.remove();
    };
  }, [currentToast]);
}
