/* ---------------------------------- @mui ---------------------------------- */
import { OutlinedInput, Stack } from '@mui/material';
/* ----------------------------------- yup ---------------------------------- */
import * as Yup from 'yup';
/* -------------------------------- snackbar -------------------------------- */
import { useSnackbar } from 'notistack';
/* ---------------------------------- react --------------------------------- */
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
/* ---------------------------------- form ---------------------------------- */
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
/* ---------------------------------- hooks --------------------------------- */
import useAuth from '../../../hooks/useAuth';

/* ---------------------------------- types --------------------------------- */

type VerifyCodeFormProps = {
  emailOrPhone: string;
};

type FormValuesProps = {
  code1: string;
  code2: string;
  code3: string;
  code4: string;
};

type ValueNames = 'code1' | 'code2' | 'code3' | 'code4';

type responseProps = {
  status: string;
  statusCode: number;
  data: [];
  message: string;
};

/* -------------------------------------------------------------------------- */

export default function VerifyCodeForm({ emailOrPhone }: VerifyCodeFormProps) {
  const navigate = useNavigate();
  const { validateOtp } = useAuth();
  const { enqueueSnackbar } = useSnackbar();

  const VerifyCodeSchema = Yup.object().shape({
    code1: Yup.string().required('Code is required'),
    code2: Yup.string().required('Code is required'),
    code3: Yup.string().required('Code is required'),
    code4: Yup.string().required('Code is required'),
  });

  const defaultValues = {
    code1: '',
    code2: '',
    code3: '',
    code4: '',
  };

  const { watch, control, setValue, handleSubmit } = useForm({
    mode: 'onBlur',
    resolver: yupResolver(VerifyCodeSchema),
    defaultValues,
  });

  const values = watch();

  useEffect(() => {
    const handlePasteClipboard = (event: ClipboardEvent) => {
      let data: string | string[] = event?.clipboardData?.getData('Text') || '';

      data = data.split('');

      [].forEach.call(document.querySelectorAll('#field-code'), (node: any, index) => {
        node.value = data[index];
        const fieldIndex = `code${index + 1}`;
        setValue(fieldIndex as ValueNames, data[index]);
      });
    };

    document.addEventListener('paste', handlePasteClipboard);
  }, [setValue]);

  const onSubmit = async (data: FormValuesProps) => {
    // @ts-ignore
    const response: responseProps = await validateOtp(emailOrPhone, Object.values(data).join(''));

    if (response.data.length === 0) {
      return enqueueSnackbar(response.message, {
        variant: 'error',
        autoHideDuration: 4000,
        preventDuplicate: true,
      });
    } else {
      enqueueSnackbar('Verify success!', { variant: 'success', autoHideDuration: 1000 });
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }

    navigate('/dashboard');
    enqueueSnackbar('Login Berhasil!', { variant: 'success' });
    localStorage.removeItem('loginOrVerifyCode');
    localStorage.removeItem('emailOrPhone');
    localStorage.removeItem('emailOrPhoneForm');
  };

  const handleChangeWithNextField = (
    event: React.ChangeEvent<HTMLInputElement>,
    handleChange: (event: React.ChangeEvent<HTMLInputElement>) => void
  ) => {
    const { maxLength, value, name } = event.target;
    const fieldIndex = name.replace('code', '');

    const fieldIntIndex = Number(fieldIndex);

    if (value.length >= maxLength) {
      if (fieldIntIndex < 6) {
        const nextfield = document.querySelector(`input[name=code${fieldIntIndex + 1}]`);

        if (nextfield !== null) {
          (nextfield as HTMLElement).focus();
        }
      }
    }

    handleChange(event);
  };

  return (
    <form onChange={handleSubmit(onSubmit)}>
      <Stack direction="row" spacing={2} justifyContent="space-evenly">
        {Object.keys(values).map((name, index) => (
          <Controller
            key={name}
            name={`code${index + 1}` as ValueNames}
            control={control}
            render={({ field }) => (
              <OutlinedInput
                {...field}
                id="field-code"
                autoFocus={index === 0}
                placeholder=""
                onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
                  handleChangeWithNextField(event, field.onChange)
                }
                inputProps={{
                  maxLength: 1,
                  sx: {
                    p: 0,
                    textAlign: 'center',
                    width: { xs: 36, sm: 56 },
                    height: { xs: 36, sm: 56 },
                  },
                }}
              />
            )}
          />
        ))}
      </Stack>
    </form>
  );
}
