import {
  IWidgetEarnableReward,
  IWidgetInteraction,
  getRewardTransactions,
  getTargetedWidgetIdAndKind,
} from '@livelike/javascript';
import { useEffect, useRef } from 'react';
import {
  getWidgetRewardsFromRewardTransactions,
  widgetStoreActions,
} from '../store';
import { useWidgetInteractions } from './useWidgetInteractions';
import { useWidgetKind } from './useWidgetKind';

export type UseLoadWidgetRewardsEffectArg = {
  widgetId: string;
};

export function useLoadWidgetRewardsEffect({ widgetId }) {
  const widgetInteractions = useWidgetInteractions({ widgetId });
  const widgetKind = useWidgetKind({ widgetId });
  const interactionsRef = useRef<IWidgetInteraction[] | null>(null);
  const rewardRef = useRef<IWidgetEarnableReward[] | null>(null);
  const mountRef = useRef(null);
  useEffect(() => {
    // avoid getting reward transactions on initial mount since we are already loading
    // widget details including reward transaction as part of useLoadWidgetEffect
    if (!mountRef.current && Array.isArray(widgetInteractions)) {
      mountRef.current = true;
      return;
    }
    // avoid loading widget rewards if there are no interactions or
    // widget interaction are same as earlier interaction
    if (!widgetInteractions?.length) {
      return;
    }
    if (
      areWidgetInteractionsSame(
        widgetInteractions,
        interactionsRef.current ?? []
      )
    ) {
      return;
    }
    interactionsRef.current = widgetInteractions;
    const timeout = setTimeout(() => {
      getTargetedWidgetIdAndKind({ widgetId, widgetKind })
        .then(({ widgetId: targettedWidgetId }) =>
          getRewardTransactions({ widgetIds: [targettedWidgetId] })
        )
        .then((res) => {
          const widgetRewards = getWidgetRewardsFromRewardTransactions(
            res.results
          );
          if (
            rewardRef.current &&
            areWidgetRewardsSame(widgetRewards, rewardRef.current)
          ) {
            return;
          }
          rewardRef.current = widgetRewards;
          // Observed a behaviour where old reward animation overlap with new reward animation
          // until old reward animation gets resetted and dereferenced
          // To avoid overlapping, we clear the existing rewards from state so that
          // there's no residue of existing reward animation
          Promise.resolve(
            widgetStoreActions.updateWidgetRewardsAction({
              widgetId,
              widgetRewards: [],
            })
          ).then(() =>
            widgetStoreActions.updateWidgetRewardsAction({
              widgetId,
              widgetRewards,
            })
          );
        });
    }, 1000);

    return () => {
      clearTimeout(timeout);
    };
  }, [widgetId, widgetKind, widgetInteractions]);
}

function areWidgetRewardsSame(
  rewardsA: IWidgetEarnableReward[],
  rewardsB: IWidgetEarnableReward[]
) {
  if (rewardsA.length !== rewardsB.length) {
    return false;
  }
  return rewardsA.every((rewardA) => {
    return !!rewardsB.find(
      ({ reward_item_id, reward_item_amount }) =>
        rewardA.reward_item_id === reward_item_id &&
        rewardA.reward_item_amount === reward_item_amount
    );
  });
}

function areWidgetInteractionsSame(
  interactionsA: IWidgetInteraction[],
  interactionsB: IWidgetInteraction[]
) {
  if (interactionsA.length !== interactionsB.length) {
    return false;
  }
  return interactionsA.every((interactionA) => {
    return !!interactionsB.find(
      ({ option_id, choice_id }) =>
        (interactionA.option_id && interactionA.option_id === option_id) ||
        (interactionA.choice_id && interactionA.choice_id === choice_id)
    );
  });
}
