import { useEffect, useRef, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useMutation } from 'react-query';

import Box from '@material-hu/mui/Box';
import Container from '@material-hu/mui/Container';
import Typography from '@material-hu/mui/Typography';
import useMediaQuery from '@material-hu/mui/useMediaQuery';

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

import humandLogo from 'src/assets/svg/humand.svg';
import api from 'src/config/api';
import { logEvent, setUser } from 'src/config/logging';
import { STEPS } from 'src/constants/community';
import { INSTANCE_CONSTANTS } from 'src/constants/instance';
import useGeneralError from 'src/hooks/useGeneralError';
import FirstStepNewCommunity from 'src/pages/newCommunity/FirstStepNewCommunity';
import SecondStepNewCommunity from 'src/pages/newCommunity/SecondStepNewCommunity';
import { login } from 'src/services/authService';
import { createInstance } from 'src/services/instance';
import { sendInvitation } from 'src/services/users';
import { EventName } from 'src/types/amplitude';
import { type MeInstance, type SendInvitationData } from 'src/types/instance';
import { type JanusMeRawResponse } from 'src/types/login';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { instanceValues, sendInvitationValues } from 'src/utils/instance';
import { checkEmptyArray, getInvitationsEmails } from 'src/utils/invitePeople';

import GoBackButton from 'src/components/dashboard/GoBackButton';

import InvitationsFeedbackCommunity from './InvitationsFeedbackCommunity';
import InvitePeopleCommunity from './InvitePeopleCommunity';
import NewCommunityCreated from './NewCommunityCreated';

const getStepContent = {
  [INSTANCE_CONSTANTS.FIRST_STEP]: () => <FirstStepNewCommunity />,
  [INSTANCE_CONSTANTS.SECOND_STEP]: () => <SecondStepNewCommunity />,
  [INSTANCE_CONSTANTS.THIRD_STEP]: ({
    instanceId,
    token,
  }: {
    instanceId: number;
    token: string;
  }) => (
    <InvitePeopleCommunity
      instanceId={instanceId}
      token={token}
    />
  ),
};

const NewCommunity = () => {
  const [currentStep, setCurrentStep] = useState(1);
  const [token, setToken] = useState('');
  const [instanceId, setInstanceId] = useState<number>();
  const [openFeedbackInvitations, setOpenFeedbackInvitations] = useState(false);
  const [invitationsEmails, setInvitationsEmails] = useState<string[]>([]);
  const showGeneralError = useGeneralError();
  const rootRef = useRef<any>(null);

  const isXs = useMediaQuery('(max-width:700px)');

  const { mutateAsync: instanceMutation, isLoading: instanceLoading } =
    useMutation((instance: FormData) => createInstance(instance), {
      onError: err => showGeneralError(err, t('CREATE_COMMUNITY_ERROR')),
    });

  const {
    mutateAsync: sendInvitationMutation,
    isLoading: sendInvitationLoading,
  } = useMutation(
    (invitationData: SendInvitationData): any => {
      const { emailsArray } = invitationData;
      return sendInvitation({ emails: emailsArray });
    },
    {
      onError: err => showGeneralError(err, t('SEND_INVITATION_ERROR')),
    },
  );

  const { t } = useLokaliseTranslation('authentication');

  useEffect(() => {
    const scrollToTop = () => {
      if (rootRef?.current?._container) {
        rootRef.current._container.scrollTop = 0;
      }
    };
    scrollToTop();
  }, [currentStep, rootRef]);

  const form = useForm({
    defaultValues: {
      firstName: '',
      lastName: '',
      email: '',
      password: '',
      companyName: '',
      companySize: '',
      companyColor: '#2DA8A4',
      language: '',
      logo: humandLogo,
      phone: null,
      sendInvitations: [{ email: '' }],
      timezone: null,
    },
  });

  const {
    getValues,
    handleSubmit,
    watch,
    formState: { isSubmitting },
  } = form;

  const submit = async (values: any) => {
    const { email, password } = values;

    const formData = instanceValues(values);
    const response = await instanceMutation(formData);
    setCurrentStep(prev => prev + 1);

    const loginResponse = await login({
      employeeInternalId: email,
      password,
      instanceId: response.data.id as number,
    });

    const { accessToken } = loginResponse.data;

    const meResponse = await api.get<JanusMeRawResponse>('janus/me', {
      headers: { Authorization: `Bearer ${accessToken}` },
    });
    const { user, instance: rawInstance } = meResponse.data;
    // Janus ships forceOtp / maxPostSizeInMb (final lowercase) while MeInstance
    // expects forceOTP / maxPostSizeInMB. Mirrors the canonical mapping in
    // mapJanusMeResponse (src/contexts/JWTContext.tsx).
    const { forceOtp, maxPostSizeInMb, ...restInstance } = rawInstance;
    const instance: MeInstance = {
      ...restInstance,
      forceOTP: forceOtp,
      maxPostSizeInMB: maxPostSizeInMb,
    };

    await setUser(user, instance);

    logEvent(EventName.INSTANCE_CREATE);

    setToken(accessToken);
    setInstanceId(response.data.id);
  };

  const handleSendInvitations = async (values: any) => {
    const { sendInvitations } = values;
    const invitationData = sendInvitationValues(sendInvitations, token);
    await sendInvitationMutation(invitationData);
    const newEmails = getInvitationsEmails(sendInvitations);
    setInvitationsEmails(newEmails);
    setOpenFeedbackInvitations(true);
    setCurrentStep(prev => prev + 1);
  };

  const handleNext = (values: any) => {
    if (currentStep === STEPS.THIRD_STEP) {
      handleSendInvitations(values);
    } else if (currentStep === STEPS.SECOND_STEP) {
      submit(values);
    } else {
      setCurrentStep(prev => prev + 1);
    }
  };

  const handleBack = () => {
    setCurrentStep(prev => prev - 1);
  };

  const getStepContentProps = {
    token,
    instanceId,
  } as { token: string; instanceId: number };

  return (
    <Box
      sx={{
        backgroundColor: 'background.default',
        height: '100vh',
        overflowY: 'auto',
        py: { xs: 2, sm: 4 },
      }}
    >
      {currentStep === 4 && !openFeedbackInvitations && (
        <NewCommunityCreated
          instanceId={instanceId as number}
          email={getValues('email')}
          password={getValues('password')}
          color={getValues('companyColor')}
        />
      )}
      {currentStep === 4 && openFeedbackInvitations && (
        <InvitationsFeedbackCommunity
          invitationsEmails={invitationsEmails}
          handleOnContinue={() => setOpenFeedbackInvitations(false)}
        />
      )}
      {currentStep < 4 && (
        <Container
          sx={{ maxWidth: { xs: '100%', sm: '60%' } }}
          maxWidth={false}
        >
          <Box
            sx={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'space-between',
            }}
          >
            <Typography
              color="secondary"
              sx={{ fontWeight: 600 }}
            >
              {t('STEP', { currentStep, totalSteps: STEPS.TOTAL_STEPS })}
            </Typography>
            {currentStep === 2 && (
              <GoBackButton
                onClick={handleBack}
                sx={{ m: 0 }}
              />
            )}
          </Box>
          <FormProvider {...form}>
            <form
              onSubmit={e => {
                e.preventDefault();
              }}
            >
              {getStepContent[currentStep](getStepContentProps)}
              <Box
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                  flexDirection: isXs ? 'column' : 'row',
                }}
              >
                <Button
                  variant="contained"
                  onClick={handleSubmit(handleNext)}
                  color="success"
                  sx={{ mt: 4, px: 4 }}
                  disabled={
                    isSubmitting ||
                    instanceLoading ||
                    sendInvitationLoading ||
                    (currentStep === STEPS.THIRD_STEP &&
                      checkEmptyArray(watch('sendInvitations')))
                  }
                >
                  <Typography sx={{ fontSize: '16px', fontWeight: 600 }}>
                    {currentStep < STEPS.THIRD_STEP
                      ? t('NEXT')
                      : t('INVITE_TEAMMATES')}
                  </Typography>
                </Button>
                {currentStep === STEPS.THIRD_STEP && (
                  <Button
                    variant="text"
                    color="secondary"
                    sx={{ mt: isXs ? 2 : 4, px: 4, ml: isXs ? 0 : 3 }}
                    onClick={() => setCurrentStep(prev => prev + 1)}
                  >
                    <Typography sx={{ fontSize: '16px', fontWeight: 600 }}>
                      {t('SKIP_STEP')}
                    </Typography>
                  </Button>
                )}
              </Box>
            </form>
          </FormProvider>
        </Container>
      )}
    </Box>
  );
};

export default NewCommunity;
