import { type FC } from 'react';
import { useMutation } from 'react-query';

import { useModal } from '@material-hu/hooks/useModal';
import { IconPhone, IconVideo } from '@material-hu/icons/tabler';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography/Typography';

import Button from '@material-hu/components/design-system/Buttons/Button';
import Dialog from '@material-hu/components/design-system/Dialog';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/amplitude';
import { focusExistingCallTab } from 'src/pages/dashboard/videoCall/utils';
import { createMartyVideoCall, ringCall } from 'src/services/streaming';
import { EventName } from 'src/types/amplitude';
import {
  CallType,
  type InitializationConfig,
  type MartyVideoCallResponse,
} from 'src/types/stream';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { isSafari } from 'src/utils/platform';
import { getUrl } from 'src/utils/stream';

import {
  FeatureNotAvailableModal,
  FeaturesNotAvailable,
} from 'src/components/FeatureNotAvailableModal';
import GettingReadyModal from 'src/components/FeatureNotAvailableModal/GettingReadyModal';

type CallButtonsProps = {
  chatId: string;
  canCall: boolean;
  isGroupCall: boolean;
  activeVideoCall?: MartyVideoCallResponse;
};

const CallButtons: FC<CallButtonsProps> = ({
  chatId,
  canCall,
  isGroupCall,
  activeVideoCall,
}) => {
  const { t } = useLokaliseTranslation('calls');
  const { enqueueSnackbar } = useHuSnackbar();
  const theme = useTheme();

  const {
    modal: featureNotAvailableModal,
    showModal: showfeatureNotAvailableModal,
    closeModal,
  } = useModal(({ featureName }: { featureName: FeaturesNotAvailable }) => (
    <FeatureNotAvailableModal
      featureName={featureName}
      onAccept={closeModal}
    />
  ));

  const {
    modal: gettingReadyModal,
    showModal: showGettingReadyModal,
    closeModal: closeGettingReadyModal,
  } = useModal(
    ({
      isVideoCall,
      onAbort,
    }: {
      isVideoCall: boolean;
      onAbort: () => void;
    }) => (
      <GettingReadyModal
        isVideoCall={isVideoCall}
        onClose={closeGettingReadyModal}
        onAbort={onAbort}
      />
    ),
    { disableEscapeKeyDown: true },
  );

  const {
    modal: noPermissionsModal,
    showModal: showNoPermissionsModal,
    closeModal: closeNoPermissionsModal,
  } = useModal(
    ({
      title,
      textBody,
      steps,
      primaryButtonClick,
    }: {
      title: string;
      textBody: string;
      steps: string;
      primaryButtonClick: () => void;
    }) => (
      <Dialog
        title={title}
        onClose={closeNoPermissionsModal}
        body={
          <Stack sx={{ gap: 2 }}>
            <Stack>
              <Typography>{textBody}</Typography>
              <Typography>{steps}</Typography>
            </Stack>
            <Typography>
              {t('permissions.allow_without_permissions')}
            </Typography>
          </Stack>
        }
        primaryButtonProps={{
          children: t('permissions.allow_without_permissions_button'),
          onClick: () => {
            primaryButtonClick();
            closeNoPermissionsModal();
          },
        }}
      />
    ),
    {
      fullWidth: true,
    },
  );

  const openWindowWithPermissionsCheck = (openWindow: () => Window | null) => {
    const newWindow = openWindow();
    if (!newWindow) {
      showNoPermissionsModal({
        title: t('permissions.title'),
        textBody: t('permissions.pop_up'),
        steps: isSafari() ? t('permissions.pop_up_safari_steps') : '',
        primaryButtonClick: openWindow,
      });
    }
  };

  const joinActiveCall = async (id: string, providerCallId: string) => {
    const url = getUrl({
      id,
      providerCallId,
      lobby: true,
    });

    const focused = await focusExistingCallTab(id);

    if (focused) {
      const existingWindow = window.open('', id);
      if (existingWindow) {
        if (existingWindow.location.href === 'about:blank') {
          existingWindow.location.href = url;
        }
        existingWindow.focus();
        return;
      }
    }

    openWindowWithPermissionsCheck(() => window.open(url, id));
  };

  const { mutate: ringCallMutation } = useMutation(
    ({
      callId,
    }: {
      callId: string;
      initializationConfig: InitializationConfig;
    }) => ringCall(callId),
    {
      onSuccess: ({ data: callInitialized }, { initializationConfig }) => {
        logEvent(EventName.CALLS_CALL_STARTED, {
          call_type: initializationConfig.cameraEnabled
            ? CallType.VIDEO
            : CallType.AUDIO,
          id: callInitialized.id,
          receivers_id: callInitialized.participants
            .map(participant => participant.id)
            .filter(
              participantId => participantId !== callInitialized.creator.id,
            ),
        });
      },
      onError: () => {
        enqueueSnackbar({
          title: t('error_init_call'),
          variant: 'error',
        });
      },
    },
  );

  const { mutateAsync: initCall } = useMutation(
    ({
      channelId,
      initializationConfig,
    }: {
      channelId: string;
      initializationConfig: InitializationConfig;
    }) => createMartyVideoCall({ channelId, initializationConfig }),
    {
      onSuccess: (data, variables) => {
        const { data: callData } = data;
        const { initializationConfig } = variables;
        const openWindow = () =>
          window.open(
            getUrl({
              id: callData.id,
              providerCallId: callData.provider_call_id,
              emitCall: true,
              initAndJoinCall: isGroupCall, // when we emit a group call we need to init and join the call
            }),
            callData.id,
          );
        openWindowWithPermissionsCheck(openWindow);
        ringCallMutation({ callId: callData.id, initializationConfig });
      },
      onError: () => {
        enqueueSnackbar({
          title: t('ERROR_INIT_CALL'),
          variant: 'error',
        });
      },
    },
  );

  const callToUser = (initializationConfig: InitializationConfig) =>
    initCall({ channelId: chatId, initializationConfig });

  const handleFeatureNotAvailable = (featureName: FeaturesNotAvailable) => {
    const timeout = setTimeout(() => {
      closeGettingReadyModal();
      showfeatureNotAvailableModal({ featureName });
    }, 5000);
    showGettingReadyModal({
      isVideoCall: featureName === FeaturesNotAvailable.VIDEO_CALL,
      onAbort: () => clearTimeout(timeout),
    });
  };

  return (
    <>
      {featureNotAvailableModal}
      {gettingReadyModal}
      {noPermissionsModal}
      {activeVideoCall && (
        <Button
          variant="success"
          size="small"
          startIcon={<IconPhone />}
          onClick={() =>
            joinActiveCall(activeVideoCall.id, activeVideoCall.provider_call_id)
          }
        >
          {t('join')}
        </Button>
      )}
      {!activeVideoCall && (
        <Stack sx={{ flexDirection: 'row' }}>
          <IconButton
            onClick={() => {
              if (canCall) {
                callToUser({ cameraEnabled: true });
                return;
              }
              handleFeatureNotAvailable(FeaturesNotAvailable.VIDEO_CALL);
            }}
          >
            <IconVideo color={theme.palette.new.text.neutral.default} />
          </IconButton>
          <IconButton
            onClick={() => {
              if (canCall) {
                callToUser({ cameraEnabled: false });
                return;
              }
              handleFeatureNotAvailable(FeaturesNotAvailable.CALL);
            }}
          >
            <IconPhone color={theme.palette.new.text.neutral.default} />
          </IconButton>
        </Stack>
      )}
    </>
  );
};

export default CallButtons;
