import React, { useCallback, useMemo } from 'react';
import {
  useInteractedWidgetOption,
  useWidgetResultState,
  useWidgetInteractionActions,
  useWidgetOptions,
  useIsWidgetOptionDisabled,
} from '../../hooks';
import { WidgetResultState } from '../../types';
import { LLWidgetOption, LLWidgetOptionProps } from './LLWidgetOption';

export type LLWidgetVoteOptionProps = {
  widgetId: string;
  optionIndex: number;
  selectedOptionIndex: number;
  correctable?: boolean;
  onOptionChange: (optionIndex: number) => void;
  OptionComponent?: typeof LLWidgetOption;
  OptionComponentStyles?: LLWidgetOptionProps['styles'];
};

export function LLWidgetVoteOption({
  widgetId,
  optionIndex,
  selectedOptionIndex: selectedOptionIndexProp,
  onOptionChange,
  correctable,
  OptionComponent = LLWidgetOption,
  OptionComponentStyles,
}: LLWidgetVoteOptionProps) {
  const { updateWidgetInteractionAction, createWidgetInteractionAction } =
    useWidgetInteractionActions({ widgetId });
  const widgetResultState = useWidgetResultState({ widgetId });
  const widgetOptions = useWidgetOptions({ widgetId });
  const interactedOption = useInteractedWidgetOption({ widgetId });
  const optionDisabled = useIsWidgetOptionDisabled({ widgetId, optionIndex });
  const interactedOptionId = interactedOption?.id;
  const widgetOption = widgetOptions?.[optionIndex];
  const widgetOptionId = widgetOption?.id;

  const selectedOptionIndex = useMemo(() => {
    // show interactedOption as selected when user has not interacted with any of the option
    // useful for inital mount of widget where selectedIndex is -1 but user has already interacted
    // with the widget before.
    if (
      interactedOptionId &&
      widgetOptionId &&
      interactedOptionId === widgetOptionId &&
      selectedOptionIndexProp < 0
    ) {
      return optionIndex;
    }
    return selectedOptionIndexProp;
  }, [
    selectedOptionIndexProp,
    widgetOptionId,
    interactedOptionId,
    optionIndex,
  ]);

  const votePercentage = useMemo(() => {
    if (!widgetOptions?.length) {
      return 0;
    }
    const totalVotes = widgetOptions.reduce(
      (total, option) => option.vote_count + total,
      0
    );
    if (!totalVotes) {
      return 0;
    }
    const percentage = Math.round(
      (widgetOptions[optionIndex].vote_count / totalVotes) * 100
    );
    return percentage < 100 ? percentage : 100;
  }, [widgetOptions, optionIndex]);

  const onOptionPressHandler = useCallback(() => {
    onOptionChange(optionIndex);
    if (interactedOption) {
      updateWidgetInteractionAction({
        interactionItem: widgetOption,
      });
    } else {
      createWidgetInteractionAction({
        interactionItem: widgetOption,
      });
    }
  }, [
    interactedOption,
    widgetId,
    widgetOption,
    optionIndex,
    selectedOptionIndex,
    updateWidgetInteractionAction,
    createWidgetInteractionAction,
  ]);

  const showWidgetResult = widgetResultState === WidgetResultState.SHOWN;

  if (!widgetOptions || !widgetOption) {
    return undefined;
  }

  return (
    <OptionComponent
      optionIndex={optionIndex}
      percentage={votePercentage}
      optionImage={widgetOption?.image_url}
      optionText={widgetOption?.description}
      optionDisabled={optionDisabled}
      showWidgetResult={showWidgetResult}
      selectedOptionIndex={selectedOptionIndex}
      onOptionChange={onOptionPressHandler}
      styles={OptionComponentStyles}
      correctOption={
        correctable && interactedOption ? widgetOption?.is_correct : undefined
      }
    />
  );
}
