import { useState } from 'react';
import { useMutation, useQueryClient } from 'react-query';

import { logEvent } from 'src/config/logging';
import useGeneralError from 'src/hooks/useGeneralError';
import { feedKeys, addVoteInPoll } from 'src/pages/dashboard/feed/queries';
import { updateGroupVoteInPoll } from 'src/pages/dashboard/groups/queries';
import { voteGroupPoll } from 'src/services/groups';
import { votePoll } from 'src/services/posts';
import { EventName } from 'src/types/amplitude';
import { Poll as PollType } from 'src/types/posts';
import { checkAndShowError } from 'src/utils/errorHandlers';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { isPollEnded, getPollEndedVoteErrorKey } from 'src/utils/poll';

type UsePollProps = {
  poll: PollType;
  postId: number;
  groupId?: string;
  isDetail?: boolean;
};

type UsePollReturn = {
  // Configuration
  isAnonymous: boolean;
  votersVisible: boolean;
  pollEnded: boolean;

  // Voting state
  selectedOption: number | null;
  isLoading: boolean;

  // Actions
  handleSelect: (optionIndex: number) => void;
  submit: () => void;
};

export const usePoll = ({
  poll,
  postId,
  groupId,
  isDetail = false,
}: UsePollProps): UsePollReturn => {
  const [selectedOption, setSelectedOption] = useState<number | null>(null);

  const showGeneralError = useGeneralError();
  const queryClient = useQueryClient();
  const { t } = useLokaliseTranslation('post');

  const onError = (err: Error) => {
    checkAndShowError(
      err,
      showGeneralError,
      t,
      [getPollEndedVoteErrorKey],
      'error_vote_poll',
    );
  };

  const voteMutation = useMutation(votePoll, {
    onSuccess: () => {
      logEvent(EventName.POST_POLL_ANSWER, { postId, pollId: poll.id });
      if (isDetail) {
        queryClient.invalidateQueries(feedKeys.detail(postId));
      } else {
        queryClient.invalidateQueries(feedKeys.list());
        if (selectedOption !== null) {
          addVoteInPoll(postId, poll.pollOptions[selectedOption].id, true);
        }
      }
    },
    onError,
  });

  const groupVoteMutation = useMutation(
    (optionId: number) => voteGroupPoll(groupId!, postId, poll.id, optionId),
    {
      onSuccess: () => {
        logEvent(EventName.GROUPS_POST_POLL_ANSWERED, {
          groupId,
          postId,
          pollId: poll.id,
        });
        if (selectedOption !== null && groupId) {
          updateGroupVoteInPoll(
            postId,
            groupId,
            poll.pollOptions[selectedOption].id,
          );
          addVoteInPoll(postId, poll.pollOptions[selectedOption].id, true);
        }
      },
      onError,
    },
  );

  const handleSelect = (optionIndex: number) => {
    setSelectedOption(optionIndex);
  };

  const submit = () => {
    if (selectedOption !== null) {
      if (groupId) {
        groupVoteMutation.mutate(poll.pollOptions[selectedOption].id);
      } else {
        voteMutation.mutate(poll.pollOptions[selectedOption].id);
      }
    }
  };

  // Configuration
  const isAnonymous = poll.pollConfiguration?.isAnonymous ?? false;
  const votersVisible = !isAnonymous;
  const pollEnded = isPollEnded(poll.pollConfiguration?.endsAt ?? null);

  return {
    // Configuration
    isAnonymous,
    votersVisible,
    pollEnded,

    // Voting state
    selectedOption,
    isLoading: voteMutation.isLoading || groupVoteMutation.isLoading,

    // Actions
    handleSelect,
    submit,
  };
};
