import React from 'react';
import { Controller, useForm } from 'react-hook-form';
import { ErrorMessage } from '@hookform/error-message';
import {
  Box,
  FormStatusMessage,
  Grid,
  GridItem,
  Icon,
  MainButton,
  MainColorType,
  makeToast,
  NumberInput,
  Text,
} from '@nova-hf/ui';
import { PAYMENT_METHODS } from 'beta/graphql/queries/paymentMethods';
import { parseMainColor } from 'beta/utils/typeGuards';
import {
  PaymentTypeV2,
  useAddPaymentMethodMutation,
  useCustomerNationalIdQuery,
} from 'typings/graphql';
import { useTranslation } from 'utils/i18n';

type AddCardProps = {
  onConfirm: () => void;
  closeModal?: () => void;
  customerId: string;
  color?: MainColorType;
  onCancel?: () => void;
};

type AddPaymentMethodForm = {
  year: string;
  month: string;
  cvc: string;
  cardNumber: string;
};

const AddPaymentCard = ({ color, customerId, onConfirm, closeModal, onCancel }: AddCardProps) => {
  const COLOR = parseMainColor(color ?? 'pink');
  const { t } = useTranslation('payments');
  const { data: customerData } = useCustomerNationalIdQuery({
    variables: { input: { id: customerId } },
  });
  const [addPaymentMethod, { loading: loadingAddPaymentMethod, error }] =
    useAddPaymentMethodMutation({
      onCompleted: (data) => {
        if (data) {
          onConfirm();
          makeToast.success(t('card.added'), '');
        }
      },
      onError: (error) => {
        if (error instanceof Error) makeToast.danger(t('card.addFail'), error.message);
      },
      refetchQueries: [
        { query: PAYMENT_METHODS, variables: { input: { id: customerId.toString() } } },
      ],
      awaitRefetchQueries: true,
    });

  const { control, clearErrors, setValue, handleSubmit } = useForm<AddPaymentMethodForm>({
    defaultValues: {
      year: '',
      month: '',
      cvc: '',
      cardNumber: '',
    },
    delayError: 500,
    mode: 'onChange',
  });

  const onSubmitNew = async (form: AddPaymentMethodForm) => {
    const { year, month, cvc, cardNumber } = form;
    clearErrors();
    await addPaymentMethod({
      variables: {
        input: {
          cardNumber: cardNumber,
          customerId: customerId.toString(),
          nationalId: customerData?.customer?.nationalId ?? '',
          cardCvc: cvc,
          type: PaymentTypeV2.CreditCard,
          cardExpiry: year + month,
        },
      },
    });
  };

  if (error && closeModal) {
    return (
      <Grid rowGap={{ lg: 9 }} gridTemplate={2}>
        <GridItem gridColumn={{ sm: 'span2' }}>
          <Box
            display="flex"
            flexDirection="row"
            alignItems="center"
            justifyContent="flex-start"
            gap={2}
            marginBottom={5}
          >
            <Icon color={COLOR} icon="addCreditcard" size={48} viewBox={24} />
            <Text variant="h6">{'Úpps, eitthvað fór úrskeiðis'}</Text>
          </Box>
          <MainButton text="Til baka" onClick={closeModal} />
        </GridItem>
      </Grid>
    );
  }

  return (
    <Box onSubmit={handleSubmit(onSubmitNew)} renderAs="form">
      <Box
        display="flex"
        flexDirection="row"
        alignItems="center"
        justifyContent="flex-start"
        gap={2}
      ></Box>
      <Box marginTop={5} id="new-card-form">
        <Grid gridTemplate={{ sm: 3, md: 5 }}>
          <GridItem gridColumn={{ sm: 'span3', md: 'span2' }}>
            <Controller
              name={'cardNumber'}
              control={control}
              rules={{
                minLength: {
                  value: 16,
                  message: t('card.cardNumberMin'),
                },
                maxLength: {
                  value: 16,
                  message: t('card.cardNumberMax'),
                },
                required: true,
              }}
              render={({ field, formState: { errors } }) => {
                const { value, name, ref } = field;
                return (
                  <>
                    <NumberInput
                      id="CreditCardInput"
                      label={t('card.number')}
                      name="Credit Card Input"
                      numberType="cc"
                      value={value}
                      ref={ref}
                      required
                      disabled={loadingAddPaymentMethod}
                      onChange={(value) => setValue('cardNumber', value)}
                    />
                    <ErrorMessage
                      errors={errors}
                      name={name}
                      render={({ message }) => (
                        <FormStatusMessage message={message} status="error" />
                      )}
                    />
                  </>
                );
              }}
            />
          </GridItem>
          <GridItem>
            <Controller
              name={'month'}
              control={control}
              rules={{
                min: {
                  value: 1,
                  message: t('card.monthFail'),
                },
                max: {
                  value: 12,
                  message: t('card.monthFail'),
                },
                required: true,
              }}
              render={({ field, formState: { errors } }) => {
                const { value, name, ref } = field;
                return (
                  <>
                    <NumberInput
                      id="CcExpMonthId"
                      label={t('card.month')}
                      name="cc-exp-month input"
                      numberType="cc-exp-month"
                      value={value}
                      ref={ref}
                      required
                      disabled={loadingAddPaymentMethod}
                      onChange={(value) => setValue('month', value)}
                    />
                    <ErrorMessage
                      errors={errors}
                      name={name}
                      render={({ message }) => (
                        <FormStatusMessage message={message} status="error" />
                      )}
                    />
                  </>
                );
              }}
            />
          </GridItem>
          <GridItem>
            <Controller
              name={'year'}
              control={control}
              rules={{
                min: {
                  value: 23,
                  message: t('card.yearFail'),
                },
                required: true,
              }}
              render={({ field, formState: { errors } }) => {
                const { value, name, ref } = field;
                return (
                  <>
                    <NumberInput
                      id="CcExpYearId"
                      label={t('card.year')}
                      name="cc-exp-year input"
                      numberType="cc-exp-year"
                      value={value}
                      ref={ref}
                      required
                      disabled={loadingAddPaymentMethod}
                      onChange={(value) => setValue('year', value)}
                    />
                    <ErrorMessage
                      errors={errors}
                      name={name}
                      render={({ message }) => (
                        <FormStatusMessage message={message} status="error" />
                      )}
                    />
                  </>
                );
              }}
            />
          </GridItem>
          <GridItem>
            <Controller
              name={'cvc'}
              control={control}
              rules={{
                minLength: {
                  value: 3,
                  message: t('card.cvcMin'),
                },
                maxLength: {
                  value: 3,
                  message: t('card.cvcMax'),
                },
                required: true,
              }}
              render={({ field, formState: { errors } }) => {
                const { value, name, ref } = field;
                return (
                  <>
                    <NumberInput
                      id="CvcId"
                      label={t('card.cvc')}
                      name="CvcInput"
                      numberType="cvc"
                      value={value}
                      ref={ref}
                      required
                      disabled={loadingAddPaymentMethod}
                      onChange={(value) => setValue('cvc', value)}
                    />
                    <ErrorMessage
                      errors={errors}
                      name={name}
                      render={({ message }) => (
                        <FormStatusMessage message={message} status="error" />
                      )}
                    />
                  </>
                );
              }}
            />
          </GridItem>
        </Grid>
      </Box>
      <Box display="flex" flexDirection={{ sm: 'column', md: 'row' }}>
        <Box marginTop={10} width={{ sm: '100%', md: '4/12' }}>
          <MainButton text={t('card.cancel')} colorScheme="white" icon="close" onClick={onCancel} />
        </Box>
        <Box marginLeft={{ md: 'auto' }} marginTop={[2, 10]} width={{ sm: '100%', md: '4/12' }}>
          <MainButton
            text={t('card.save')}
            colorScheme={COLOR}
            icon="longArrowRight"
            isLoading={loadingAddPaymentMethod}
            isSubmitButton={true}
          />
        </Box>
      </Box>
    </Box>
  );
};
export default AddPaymentCard;
