import {
  getMilliseconds,
  SINGLE_INTERACTION_WIDGET_KINDS,
} from '@livelike/javascript';
import { useCallback, useMemo } from 'react';
import { widgetStore } from '../store';
import { WidgetUIPhase } from '../types';
import { useSelectedFieldStore } from './useSelectedFieldStore';
import { useWidgetActions } from './useWidgetActions';
import { useWidgetInteractions } from './useWidgetInteractions';
import { useWidgetKind } from './useWidgetKind';
import { useWidgetUIPhase } from './useWidgetUIPhase';
import { useIsTimelineWidget } from './useIsTimelineWidget';

export type UseWidgetInteractiveTimeoutArg = {
  widgetId: string;
  /** custom interactiveTimeout, defaults to the timeout value set when creating widget in producer suite */
  interactiveTimeout?: number | null;
  /** function to be called when widget timeouts */
  onInteractiveTimeout?: () => void;
};

export type UseWidgetInteractiveTimeoutResult = {
  /** resulted timeout value to be used by LLWidgetHeader */
  interactiveTimeout: number | null;
  /** resulted timeout handler function to be used by LLWidgetHeader */
  onInteractiveTimeout: () => void;
};

/**
 * @description useWidgetInteractiveTimeout hook is to derive resulted interactiveTimeout based on
 * the passed interactiveTimeout value that in turns drives widget UI phases.
 * For example, once the widget timeouts, widget UI phase would transition from INTERACTIVE to TIMED_OUT
 * which would turn the widget into a non interact-able widget.
 * Resulted interactiveTimeout value is used by `LLWidgetHeader` component.
 * @since 0.1.0
 */
export const useWidgetInteractiveTimeout = ({
  widgetId,
  interactiveTimeout: interactiveTimeoutProp,
  onInteractiveTimeout: onInteractiveTimeoutProp,
}: UseWidgetInteractiveTimeoutArg): UseWidgetInteractiveTimeoutResult => {
  const { updateWidgetUIPhaseAction } = useWidgetActions({ widgetId });
  const widgetUIPhase = useWidgetUIPhase({ widgetId });
  const isTimelineWidget = useIsTimelineWidget({ widgetId });
  const widgetInteractiveDuration = useSelectedFieldStore(
    widgetStore,
    () => widgetStore.get()[widgetId]?.widgetPayload?.timeout
  );
  const widgetKind = useWidgetKind({ widgetId });
  const widgetInteractions = useWidgetInteractions({ widgetId });
  const onInteractiveTimeout = useCallback(() => {
    updateWidgetUIPhaseAction({
      widgetId,
      widgetUIPhase: WidgetUIPhase.INTERACTIVE_TIMED_OUT,
    });
    onInteractiveTimeoutProp?.();
  }, [widgetId, onInteractiveTimeoutProp]);

  const interactiveTimeout = useMemo(() => {
    const isExpired = widgetUIPhase === WidgetUIPhase.EXPIRED;
    const isSubmitted = widgetUIPhase === WidgetUIPhase.SUBMITTED;
    const isFollowUpPublished =
      widgetUIPhase === WidgetUIPhase.FOLLOW_UP_PUBLISHED;
    const isInteractiveTimedOut =
      widgetUIPhase === WidgetUIPhase.INTERACTIVE_TIMED_OUT;
    if (isExpired || isInteractiveTimedOut) {
      return null;
    }
    if (isFollowUpPublished && !isTimelineWidget) {
      return null;
    }
    // set interactive timeout to null if widget interaction is already submitted
    // for single interaction widgets
    if (
      SINGLE_INTERACTION_WIDGET_KINDS.includes(widgetKind) &&
      isSubmitted &&
      !isTimelineWidget
    ) {
      return null;
    }
    if (interactiveTimeoutProp !== undefined) {
      return interactiveTimeoutProp;
    }
    return widgetInteractiveDuration
      ? getMilliseconds(widgetInteractiveDuration)
      : null;
  }, [
    widgetUIPhase,
    interactiveTimeoutProp,
    widgetInteractiveDuration,
    widgetInteractions,
    isTimelineWidget,
  ]);

  return {
    interactiveTimeout,
    onInteractiveTimeout,
  };
};
