import React, { useEffect, useRef, useState } from 'react';
import { FormStatusMessage, GridItem, makeToast } from '@nova-hf/ui';
import { Controller, useForm } from 'react-hook-form';

import { ErrorMessage } from '@hookform/error-message';
import {
  UpdateCustomerInput,
  useUpdateCustomerMutation,
  useSendNumberVerificationChallengeMutation,
  Maybe,
  useSendEmailVerificationChallengeMutation,
  Customer,
} from 'typings/graphql';
import { ConfirmationModal } from '../components/ConfirmationModal';
import { InputWithButtons } from '../components/InputWithButtons';
import { useTranslation } from 'utils/i18n';
import { emailValidate } from 'utils/helpers';
import { useRouter } from 'next/router';

type ContactInformationProps = {
  customerId: string;
  customer?: Maybe<Customer>;
  onRefetch?: () => void;
};
export const ContactInformation = ({
  customerId,
  customer,
  onRefetch,
}: ContactInformationProps) => {
  const { t } = useTranslation('stillingar');
  const emailRef = useRef<HTMLInputElement>(null);
  const { query } = useRouter();

  const { control, watch, setError, setValue } = useForm<UpdateCustomerInput>({
    defaultValues: {
      primaryPhoneNumber: '',
      email: '',
    },
    delayError: 500,
    mode: 'onChange',
  });

  const [updateCustomer, { loading: updateCustomerLoading }] = useUpdateCustomerMutation();

  const [sendNumberVerificationChallenge, { loading: newTextChallengeLoading }] =
    useSendNumberVerificationChallengeMutation({
      onCompleted(data) {
        if (data?.sendNumberVerificationChallenge.NumberVerificationChallenge?.id) {
          const phoneNumberChallengeId: string =
            data.sendNumberVerificationChallenge.NumberVerificationChallenge.id;
          setChallengeId(phoneNumberChallengeId);
          onRefetch && onRefetch();
        }
      },
    });

  const [sendEmailVerification, { loading: newEmailChallengeLoading }] =
    useSendEmailVerificationChallengeMutation();

  const [challengeId, setChallengeId] = useState('');
  const { primaryPhoneNumber, email } = watch();

  useEffect(() => {
    if (customer) {
      setValue('email', customer.email ?? '');
      setValue('primaryPhoneNumber', customer.primaryPhoneNumber ?? '');
    }
  }, [customer]);

  useEffect(() => {
    if (query.email && emailRef.current) {
      emailRef.current.scrollIntoView({
        block: 'center',
        behavior: 'smooth',
      });
    }
  }, [emailRef.current]);

  const handleSendNewTextVerification = async () => {
    try {
      const { data } = await sendNumberVerificationChallenge({
        variables: {
          input: {
            customerId: customerId,
            primaryNumber: primaryPhoneNumber ?? '',
          },
        },
      });
      if (data?.sendNumberVerificationChallenge.error) {
        setError('primaryPhoneNumber', {
          message: data?.sendNumberVerificationChallenge.error.message,
        });
      }
    } catch (error) {
      if (error instanceof Error) {
        setError('primaryPhoneNumber', { message: error.message });
      }
    }
  };

  const handleSendEmailVerification = async () => {
    if (email) {
      try {
        const { data } = await sendEmailVerification({
          variables: {
            input: {
              customerId: customerId,
              email: email ?? '',
            },
          },
        });
        if (data?.sendEmailVerificationChallenge.emailVerificationChallenge?.id) {
          makeToast.success(t('contactInformationTab.gotNewConfirmationMail'), '');
        } else {
          makeToast.danger(
            t('contactInformationTab.sometingFailed'),
            t('contactInformationTab.tryAgain'),
          );
        }
      } catch (e) {
        makeToast.danger(
          t('contactInformationTab.sometingFailed'),
          t('contactInformationTab.tryAgain'),
        );
      }
    }
  };

  const handleUpdatePrimaryPhoneNumber = async () => {
    if (customer?.primaryPhoneNumber === primaryPhoneNumber) {
      handleSendNewTextVerification();
    } else {
      try {
        const { data } = await updateCustomer({
          variables: {
            input: { customerId: customerId, primaryPhoneNumber: primaryPhoneNumber },
          },
        });
        if (data?.updateCustomer?.customer?.primaryPhoneNumber) {
          handleSendNewTextVerification();
        }
        if (data?.updateCustomer?.error) {
          setError('primaryPhoneNumber', {
            message:
              data.updateCustomer.error.message ??
              `${t('contactInformationTab.sometingFailed')} ${t('contactInformationTab.tryAgain')}`,
          });
        }
      } catch (error) {
        if (error instanceof Error) {
          setError('primaryPhoneNumber', { message: error.message });
        }
      }
    }
  };

  const handleUpdateEmail = async () => {
    if (customer?.email === email) {
      handleSendEmailVerification();
    } else {
      try {
        const { data } = await updateCustomer({
          variables: {
            input: { customerId: customerId, email: email },
          },
        });
        if (data?.updateCustomer?.customer.email) {
          onRefetch && onRefetch();
        }
        if (data?.updateCustomer?.error) {
          setError('email', {
            message:
              data.updateCustomer.error.message ??
              `${t('contactInformationTab.sometingFailed')} ${t('contactInformationTab.tryAgain')}`,
          });
        }
      } catch (error) {
        if (error instanceof Error) {
          setError('email', { message: error.message });
        }
      }
    }
  };

  return (
    <>
      <GridItem gridColumn={{ sm: 'span4', md: 'span12' }}>
        <Controller
          name={'email'}
          control={control}
          rules={{
            validate: {
              emailValidation: (value) => {
                return emailValidate(value ?? '');
              },
            },
          }}
          render={({ field, formState: { errors } }) => {
            const { value, ...rest } = field;
            return (
              <div ref={emailRef}>
                <InputWithButtons
                  id="email"
                  label={t('contactInformationTab.emailLabel')}
                  value={value ?? ''}
                  {...rest}
                  isVerified={
                    !!customer?.isEmailVerified &&
                    customer.email === email &&
                    !updateCustomerLoading
                  }
                  isValid={!errors.email}
                  originalValue={customer?.email ?? ''}
                  disabled={updateCustomerLoading || newEmailChallengeLoading}
                  onSubmitClick={() => handleUpdateEmail()}
                  loading={newEmailChallengeLoading}
                />
                <ErrorMessage
                  errors={errors}
                  name="email"
                  render={({ message }) => (
                    <FormStatusMessage
                      message={
                        errors.email?.type === 'emailValidation'
                          ? t('contactInformationTab.notValidEmail')
                          : message
                      }
                      status="error"
                    />
                  )}
                />
              </div>
            );
          }}
        />
      </GridItem>
      <GridItem gridColumn={{ sm: 'span4', md: 'span12' }}>
        <Controller
          name={'primaryPhoneNumber'}
          control={control}
          rules={{
            minLength: {
              value: 7,
              message: t('contactInformationTab.notValidPhoneNumber'),
            },
            maxLength: {
              value: 7,
              message: t('contactInformationTab.notValidPhoneNumber'),
            },
          }}
          render={({ field, formState: { errors } }) => {
            const { value, ...rest } = field;
            return (
              <>
                <InputWithButtons
                  id="phoneNumber"
                  label={t('contactInformationTab.primaryPhoneNumberLabel')}
                  value={value ?? ''}
                  {...rest}
                  isVerified={
                    !!customer?.isPhoneNumberVerified &&
                    customer?.primaryPhoneNumber === primaryPhoneNumber &&
                    !newTextChallengeLoading &&
                    !updateCustomerLoading
                  }
                  autoComplete="tel-national"
                  isValid={!errors.primaryPhoneNumber}
                  disabled={updateCustomerLoading || newTextChallengeLoading}
                  originalValue={customer?.primaryPhoneNumber ?? ''}
                  onSubmitClick={() => handleUpdatePrimaryPhoneNumber()}
                  loading={newTextChallengeLoading}
                  type="tel"
                  maxLength={7}
                />
                <ErrorMessage
                  errors={errors}
                  name="primaryPhoneNumber"
                  render={({ message }) => <FormStatusMessage message={message} status="error" />}
                />
              </>
            );
          }}
        />
      </GridItem>

      <ConfirmationModal
        isVisible={!!challengeId}
        phoneNumber={primaryPhoneNumber ?? ''}
        challengeId={challengeId}
        onVisibilityChange={(isVisible) => setChallengeId(!isVisible ? '' : challengeId)}
        onClose={() => {
          onRefetch && onRefetch();
          setChallengeId('');
        }}
      />
    </>
  );
};
