import { FC } from 'react';

import { useMutation } from 'react-query';

import { AxiosResponse } from 'axios';
import { useModal } from '@material-hu/hooks/useModal';
import { IconTrash } from '@material-hu/icons/tabler';
import IconButton, { IconButtonProps } from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';

import useTheme from '@material-hu/mui/styles/useTheme';
import Typography from '@material-hu/mui/Typography/Typography';

import Button, {
  ButtonProps,
} from '@material-hu/components/design-system/Buttons/Button';
import Dialog from '@material-hu/components/design-system/Dialog';
import ProgressBar from '@material-hu/components/design-system/ProgressIndicators/ProgressBar';
import Switcher from '@material-hu/components/design-system/Switcher';
import Tooltip from '@material-hu/components/design-system/Tooltip';
import useGeneralError from 'src/hooks/useGeneralError';
import {
  deleteLivestreamPoll,
  endLivestreamPoll,
  initLivestreamPoll,
  showLivestreamPollFinalResults,
  updateLivestreamPollConfiguration,
} from 'src/services/streaming';
import { Poll, PollStatus, StreamStatus } from 'src/types/stream';
import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  deletePollData,
  invalidatePollDataQueries,
  optimisticPollDataRestore,
  optimisticUpdatePollData,
  updatePollData,
} from '../../../queries';
import { getPollStatus } from '../../../utils';

type ItemDetailProps = {
  streamId: string;
  poll: Poll;
  streamStatus: StreamStatus;
  isAnotherPollActive: boolean;
};

const ItemDetail: FC<ItemDetailProps> = props => {
  const { streamId, poll, streamStatus, isAnotherPollActive } = props;
  const { t } = useLokaliseTranslation('livestream');
  const showGeneralError = useGeneralError();
  const theme = useTheme();

  const { startsAt, endsAt } = poll.pollConfiguration;
  const pollStatus = getPollStatus(startsAt, endsAt);
  const showShowResultsSwitcher = pollStatus !== PollStatus.ENDED;

  const updatePollMutation = useMutation(
    (variables: { showResults: boolean }) =>
      updateLivestreamPollConfiguration(streamId, poll.id, {
        viewVotesResult: variables.showResults,
      }),
    {
      onMutate: async variables => {
        const previousPolls = await optimisticUpdatePollData(streamId, {
          ...poll,
          pollConfiguration: {
            ...poll.pollConfiguration,
            viewVotesResult: variables.showResults,
          },
        });
        return { previousPolls };
      },
      onError: (error, variables, context) => {
        optimisticPollDataRestore(streamId, context?.previousPolls);
        showGeneralError(error, t('polls.update_error'));
      },
      onSettled: () => {
        invalidatePollDataQueries(streamId);
      },
    },
  );
  const deletePollMutation = useMutation(
    () => deleteLivestreamPoll(streamId, poll.id),
    {
      onSuccess: () => {
        deletePollData(streamId, poll.id);
        closeDeletePollModal();
      },
      onError: error => {
        showGeneralError(error, t('polls.delete_dialog.error'));
      },
    },
  );

  const initPollMutation = useMutation(
    () => initLivestreamPoll(streamId, poll.id),
    {
      onSuccess: (response: AxiosResponse<Poll>) => {
        updatePollData(streamId, response.data);
      },
      onError: error => {
        showGeneralError(error, t('polls.init_error'));
      },
    },
  );

  const endPollMutation = useMutation(
    () => endLivestreamPoll(streamId, poll.id),
    {
      onSuccess: (response: AxiosResponse<Poll>) => {
        updatePollData(streamId, response.data);
      },
      onError: error => {
        showGeneralError(error, t('polls.end_error'));
      },
    },
  );

  const showFinalResultsMutation = useMutation(
    (variables: { show: boolean }) =>
      showLivestreamPollFinalResults(streamId, poll.id, variables.show),
    {
      onSuccess: (response: AxiosResponse<Poll>) => {
        updatePollData(streamId, response.data);
      },
      onError: error => {
        showGeneralError(error, t('polls.show_results_error'));
      },
    },
  );

  const {
    modal: deletePollModal,
    showModal: showDeletePollModal,
    closeModal: closeDeletePollModal,
  } = useModal(
    () => (
      <Dialog
        title={t('polls.delete_dialog.title')}
        body={<Typography>{t('polls.delete_dialog.description')}</Typography>}
        onClose={closeDeletePollModal}
        secondaryButtonProps={{
          children: t('general:cancel'),
          onClick: closeDeletePollModal,
        }}
        primaryButtonProps={{
          children: t('general:delete'),
          loading: deletePollMutation.isLoading,
          onClick: () => {
            deletePollMutation.mutate();
          },
        }}
      />
    ),
    {
      fullWidth: true,
    },
  );

  const pollNotInitMessage =
    streamStatus === StreamStatus.Finished
      ? t('polls.not_init_after_live')
      : t('polls.not_init_before_live');
  const buttonsPropsByPollStatus: Record<
    PollStatus,
    Array<
      | (ButtonProps & {
          disabledTooltipMessage?: string;
        })
      | (IconButtonProps & {
          icon: React.ReactNode;
        })
    >
  > = {
    [PollStatus.IDLE]: [
      {
        id: 'idle-delete',
        icon: <IconTrash />,
        size: 'large',
        onClick: () => showDeletePollModal(),
      },
      {
        id: 'idle-start',
        variant: 'primary',
        size: 'small',
        children: t('general:start'),
        disabled:
          isAnotherPollActive || streamStatus !== StreamStatus.Streaming,
        disabledTooltipMessage: isAnotherPollActive
          ? t('polls.not_init_other_active')
          : pollNotInitMessage,
        onClick: () => initPollMutation.mutate(),
        loading: initPollMutation.isLoading,
      },
    ],
    [PollStatus.ACTIVE]: [
      {
        id: 'active-finish',
        variant: 'primary',
        size: 'small',
        children: t('general:finish'),
        onClick: () => endPollMutation.mutate(),
        loading: endPollMutation.isLoading,
      },
    ],
    [PollStatus.ENDED]: [
      {
        id: 'ended-delete',
        icon: <IconTrash />,
        size: 'large',
        onClick: () => showDeletePollModal(),
      },
      {
        id: 'ended-show-results',
        variant: 'secondary',
        size: 'small',
        children: poll.pollConfiguration.showFinalResult
          ? t('polls.hide_results_button')
          : t('polls.show_results_button'),
        disabled: isAnotherPollActive || streamStatus === StreamStatus.Finished,
        disabledTooltipMessage: isAnotherPollActive
          ? t('polls.not_show_results_other_active')
          : t('polls.not_show_results_after_live'),
        onClick: () =>
          showFinalResultsMutation.mutate({
            show: !poll.pollConfiguration.showFinalResult,
          }),
        loading: showFinalResultsMutation.isLoading,
      },
      {
        id: 'ended-start',
        variant: 'primary',
        size: 'small',
        children: t('polls.restart'),
        disabled: isAnotherPollActive || streamStatus === StreamStatus.Finished,
        disabledTooltipMessage: isAnotherPollActive
          ? t('polls.not_restart_other_active')
          : t('polls.not_restart_after_live'),
        onClick: () => initPollMutation.mutate(),
        loading: initPollMutation.isLoading,
      },
    ],
  };

  return (
    <>
      {deletePollModal}
      <Stack sx={{ gap: 4.5 }}>
        <Stack sx={{ gap: 2 }}>
          {poll.pollOptions.map(option => (
            <ProgressBar
              key={option.id}
              variant="determinate"
              title={option.option}
              current={option.answerCount}
              total={poll.totalAnswerCount || 100}
              hasPercentage
              withEllipsis
              sx={{
                '& .MuiStack-root:first-of-type .MuiTypography-root': {
                  whiteSpace: 'nowrap',
                  overflow: 'hidden',
                  textOverflow: 'ellipsis',
                  width: 'calc(100% - 20px)',
                  color: theme.palette.new.text.neutral.default,
                  fontWeight: 'regular',
                },
              }}
            />
          ))}
        </Stack>
        {showShowResultsSwitcher && (
          <Switcher
            title={t('polls.show_results')}
            titleProps={{
              variant: 'globalS',
              color: 'new.text.neutral.default',
            }}
            value={poll.pollConfiguration.viewVotesResult}
            onChange={value =>
              updatePollMutation.mutate({ showResults: value })
            }
          />
        )}
        <Stack sx={{ flexDirection: 'row', gap: 2, justifyContent: 'end' }}>
          {buttonsPropsByPollStatus[pollStatus].map(buttonProps => {
            if ('icon' in buttonProps) {
              return (
                <IconButton
                  key={buttonProps.id}
                  onClick={buttonProps.onClick}
                  size={buttonProps.size}
                  sx={{
                    '& svg, &:hover svg': {
                      stroke: theme.palette.newBase?.brand[900],
                    },
                  }}
                >
                  {buttonProps.icon}
                </IconButton>
              );
            }

            return (
              <Tooltip
                key={buttonProps.id}
                disableTooltip={!buttonProps.disabled}
                description={buttonProps.disabledTooltipMessage}
              >
                <Stack>
                  <Button
                    variant={buttonProps.variant}
                    disabled={buttonProps.disabled}
                    onClick={buttonProps.onClick}
                    startIcon={buttonProps.startIcon}
                    size={buttonProps.size}
                    loading={buttonProps.loading}
                  >
                    {buttonProps.children}
                  </Button>
                </Stack>
              </Tooltip>
            );
          })}
        </Stack>
      </Stack>
    </>
  );
};

export default ItemDetail;
