import { FC, useEffect, useRef } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation, useQuery } from 'react-query';
import { useLocation, useNavigate } from 'react-router';

import { AxiosError } from 'axios';
import Divider from '@material-hu/mui/Divider';
import Stack from '@material-hu/mui/Stack';

import HuAvatar from '@material-hu/components/design-system/Avatar';
import Button from '@material-hu/components/design-system/Buttons/Button';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuFormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';
import HuTitle from '@material-hu/components/design-system/Title';

import useGeneralError from 'src/hooks/useGeneralError';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import useScrollReset from 'src/hooks/useScrollReset';
import {
  getKioskTerminal,
  linkKioskTerminal,
} from 'src/services/timeTrackingService';
import { ResponseError } from 'src/types/services';
import { TerminalLinkStatus } from 'src/types/timeTracking';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { transformWhiteSpaces } from 'src/utils/inputUtils';
import { sToMs } from 'src/utils/timeUtils';
import {
  validateMinStringRule,
  validateRequiredStringRule,
} from 'src/utils/validation';

import { invalidateKioskTerminals, timeTrackingKeys } from '../../queries';
import { timeTrackingRoutes } from '../../routes';
import SectionHeader from '../../SectionHeader';
import KioskStoreQR from '../components/KioskStoreQR';
import { kioskFields } from '../form';

const POLLIN_SECONDS_INTERVAL = 1;
const POLLIN_COUNT_LIMIT = 10;
const CODE_LENGTH = 12;

const LinkKioskTerminal: FC = () => {
  const { t } = useLokaliseTranslation('time_tracker');
  const HuGoThemeProvider = useHuGoTheme();
  const navigate = useNavigate();
  const { state } = useLocation();
  const { id: terminalId } = state as { id: number };
  const refetchCount = useRef(1);

  const { enqueueSnackbar } = useHuSnackbar();
  const showGeneralError = useGeneralError();

  // Reset scroll to top when component mounts
  useScrollReset({ containerSelector: '#dashboard-layout-content' });

  const form = useForm({
    defaultValues: {
      code: '',
    },
  });

  const {
    mutate: linkTerminalMutation,
    isLoading: isLinking,
    isSuccess: mutationSucceeded,
  } = useMutation((code: string) => linkKioskTerminal(terminalId, { code }), {
    onSuccess: async () => {
      await invalidateKioskTerminals({ refetchInactive: true });
    },
    onError: (err: AxiosError<ResponseError>) => {
      if (err.response?.data?.code === 'NOT_FOUND') {
        form.setError(kioskFields.link.code, {
          message: t('kiosk.ERROR_CODE'),
        });
      } else {
        showGeneralError(
          err,
          t('kiosk.LINK_ERROR'),
          t('kiosk.LINK_ERROR_DESCRIPTION'),
        );
      }
    },
  });

  const { isFetching: isFetchingTerminalStatus } = useQuery(
    timeTrackingKeys.kioskTerminal(terminalId),
    () => getKioskTerminal(terminalId),
    {
      select: response => response.data.status,
      refetchInterval: sToMs(POLLIN_SECONDS_INTERVAL),
      staleTime:
        refetchCount.current <= POLLIN_COUNT_LIMIT
          ? sToMs(POLLIN_SECONDS_INTERVAL)
          : Infinity,
      refetchIntervalInBackground: true,
      enabled: mutationSucceeded && refetchCount.current <= POLLIN_COUNT_LIMIT,
      onSuccess: response => {
        if (response === TerminalLinkStatus.ACTIVE) {
          enqueueSnackbar({
            title: t('kiosk.LINK_SUCCESS'),
            description: t('kiosk.LINK_SUCCESS_DESCRIPTION'),
            variant: 'success',
          });
          navigate(timeTrackingRoutes.kioskBase());
        }
      },
      onSettled: () => {
        if (refetchCount.current + 1 === POLLIN_COUNT_LIMIT) {
          enqueueSnackbar({
            title: t('kiosk.LINK_PENDING'),
            description: t('kiosk.LINK_PENDING_DESCRIPTION'),
            variant: 'warning',
          });
          navigate(timeTrackingRoutes.kioskBase());
        }
        refetchCount.current = refetchCount.current + 1;
      },
    },
  );

  const submit = form.handleSubmit(({ code }) => {
    refetchCount.current = 1;
    linkTerminalMutation(code);
  });

  useEffect(() => {
    if (terminalId === undefined) {
      navigate(timeTrackingRoutes.kioskBase());
    }
  }, []);

  const isPolling =
    isFetchingTerminalStatus ||
    (refetchCount.current > 1 && refetchCount.current < POLLIN_COUNT_LIMIT);

  return (
    <HuGoThemeProvider>
      <FormProvider {...form}>
        <form
          noValidate
          onSubmit={submit}
          style={{ height: '100%' }}
        >
          <Stack
            sx={{
              backgroundColor: ({ palette }) =>
                palette.new.background.layout.default,
              minHeight: '100%',
            }}
          >
            <SectionHeader
              goBack={() => {
                navigate(timeTrackingRoutes.kioskBase());
              }}
              title={t('kiosk.LINK_TERMINAL')}
            />
            <Stack
              sx={{
                height: '100%',
                flex: 1,
                '& > *': { px: '26%' },
              }}
            >
              <Stack
                sx={{
                  flex: 1,
                  pb: 5,
                  pt: 3,
                }}
              >
                <HuTitle
                  variant="L"
                  title={t('kiosk.ADD_CODE')}
                  description={t('kiosk.ADD_CODE_DESCRIPTION')}
                  sx={{ mb: 3 }}
                />
                <HuCardContainer fullWidth>
                  <HuFormInputClassic
                    name={kioskFields.link.code}
                    inputProps={{
                      label: t('kiosk.LINKING_CODE'),
                      placeholder: t('kiosk.CODE'),
                      maxLength: CODE_LENGTH,
                      transform: transformWhiteSpaces(3),
                    }}
                    rules={{
                      validate: {
                        required: validateRequiredStringRule,
                        minLength: validateMinStringRule(
                          CODE_LENGTH,
                          t('kiosk.CODE_LENGTH_ERROR'),
                        ),
                      },
                    }}
                  />
                </HuCardContainer>
                <Divider sx={{ my: 3, borderWidth: '0.5px' }} />
                <HuTitle
                  variant="M"
                  title={t('kiosk.REMEMBER_APP')}
                  sx={{ mb: 2 }}
                />
                <HuCardContainer
                  padding={24}
                  sx={{ mb: 2 }}
                  fullWidth
                >
                  <Stack sx={{ flexDirection: 'row', gap: 2, mb: 3 }}>
                    <HuAvatar text="1" />
                    <HuTitle
                      variant="M"
                      title={t('kiosk.LINK_STEP_TITLE_1')}
                      description={t('kiosk.LINK_STEP_DESCRIPTION_1')}
                    />
                  </Stack>
                  <KioskStoreQR />
                </HuCardContainer>
                <HuCardContainer
                  padding={24}
                  fullWidth
                >
                  <Stack sx={{ flexDirection: 'row', gap: 2 }}>
                    <HuAvatar text="2" />
                    <HuTitle
                      variant="M"
                      title={t('kiosk.INPUT_CODE')}
                      description={t('kiosk.INPUT_CODE_DESCRIPTION')}
                    />
                  </Stack>
                </HuCardContainer>
              </Stack>
              <Stack
                sx={{
                  backgroundColor: theme =>
                    theme.palette.new.background.elements.grey,
                  bottom: 0,
                  flexDirection: 'row',
                  justifyContent: 'flex-end',
                  position: 'sticky',
                  py: 2,
                  width: '100%',
                }}
              >
                <Button
                  variant="primary"
                  size="large"
                  type="submit"
                  loading={isLinking || isPolling}
                  onClick={submit}
                >
                  {t('kiosk.LINK')}
                </Button>
              </Stack>
            </Stack>
          </Stack>
        </form>
      </FormProvider>
    </HuGoThemeProvider>
  );
};

export default LinkKioskTerminal;
