import { useState } from 'react';
import { useQuery, useMutation } from '@apollo/client';
import { useTranslation } from 'utils/i18n';

import { GridDeprecated, Row, Col, PaymentSection, Button, FormWrapper, NumberTextBox, CreditCard, ErrorMessage, Card } from '@nova-hf/ui';
import { inject } from 'mobx-react';

import { CARDS } from 'graphql/queries/cards';
import { SUBSCRIPTION_PAYMENT_METHOD } from 'graphql/queries/subscriptionPaymentMethod';
import { ADD_CARD } from 'graphql/mutations/cards';
import { IUserData, ISubscriptionPaymentMethodData } from 'typings';
import formElementToObject from 'utils/formElementToObject';

import { useUpdateSubscriptionPaymentMethodMutation } from 'typings/graphql';

interface IPaymentProps {
  color?: string;
  authentication?: any;
  subId: string;
}

interface IAddCardProps {
  color?: string;
  authentication?: any;
  onComplete: () => void;
}

const AddCard = ({ color = 'pink', authentication: { accountInput }, onComplete }: IAddCardProps) => {
  const { t } = useTranslation('common');

  const [addCard, { loading }] = useMutation(ADD_CARD);
  const [submitted, setSubmitted] = useState(false);
  const [message, setMessage] = useState('');

  const onSubmit = async (e: any) => { // TODO(GUNNAR): type form stuff
    e.preventDefault();

    setSubmitted(false);
    setMessage('');

    const target: HTMLFormElement = e.target;

    if (!target.checkValidity()) {
      const firstInvalid: any = Object.values(e.target.elements).find((el: any) => !el.validity.valid);
      setSubmitted(true);
      if (firstInvalid) {
        firstInvalid.focus();
      }
      return;
    }

    const input: any = formElementToObject(e.target.elements);
    const { cardNumber, ...rest } = input;

    try {
      const res = await addCard({
        variables: {
          input: {
            isDefault: true,
            ssn: accountInput?.ssn,
            cardNumber: cardNumber.replace(/\s/g, ''),
            ...rest,
          },
        },
        refetchQueries: ['cards'],
      });

      if (res.data.addCard.error) {
        setMessage(res.data.addCard.error.message);
      } else {
        setMessage('');
        onComplete();
      }

    } catch (e) {
      setMessage(`${t('errors.general')}: ${e.message}`);
    }

  };

  return (
    <form onSubmit={onSubmit} noValidate id="card-form">
      {message && (
        <ErrorMessage>{message}</ErrorMessage>
      )}
      <FormWrapper color={color} submitted={submitted}>

        <NumberTextBox
          data-key="cardNumber"
          label={t('forms.cc.cardnumber')}
          name="cc-number"
          autoComplete="cc-number"
          errorType="cc"
          cc
          required
        />
        <CreditCard>
          <NumberTextBox
            data-key="expiryMonth"
            label={t('forms.cc.month')}
            name="cc-exp-month"
            autoComplete="cc-exp-month"
            maxLength="2"
            errorType="mm"
            required
          />
          <NumberTextBox
            data-key="expiryYear"
            label={t('forms.cc.year')}
            name="cc-exp-year"
            autoComplete="cc-exp-year"
            length="2"
            errorType="yy"
            required
          />
          <NumberTextBox
            data-key="cvc"
            label={t('forms.cc.cvc')}
            name="cc-exp-csc"
            autoComplete="cc-exp-csc"
            length="3"
            errorType="cvc"
            required
          />
        </CreditCard>
        <Button background={color} type="submit" loading={loading} arrowRight>Vista</Button>
      </FormWrapper>
    </form>
  );
};

const Payment = ({ color = 'pink', authentication, subId }: IPaymentProps) => {
  const { t } = useTranslation('settings');
  const { accountInput } = authentication;

  const { loading, error, data } = useQuery<IUserData>(CARDS, { variables: { accountInput } });
  const { error: subscriptionPaymentMethodError, data: subscriptionPaymentMethodData } =
    useQuery<ISubscriptionPaymentMethodData>(SUBSCRIPTION_PAYMENT_METHOD, { variables: { subscriptionId: subId } });

  const subscriptionPaymentMethodSavedPaymentId = subscriptionPaymentMethodData?.subscriptionPaymentMethod?.paymentMethod?.id;

  const [updateSubscriptionPaymentMethod] = useUpdateSubscriptionPaymentMethodMutation();
  // TODO -> Handle errors
  const [showAdd, setShowAdd] = useState(false);

  if (loading || error || !data) {
    return (<div>Loading...</div>);
  }

  if (subscriptionPaymentMethodError) {
    return (
      <ErrorMessage>Tókst ekki að sækja greiðslumáta</ErrorMessage>
    );
  }
  const { me: { cards } } = data;

  return (
    <>
      <PaymentSection
        title={t('payment.subscription.title')}
        subtitle={t('payment.subscription.subtitle')}
        smallerTitle
        fullWidth
        noSpacingTop
      >
        {!subscriptionPaymentMethodSavedPaymentId &&
          <div>Enginn greiðslumáti fannst, endilega smelltu á þann greiðslumáta sem þú vilt hafa eða skráðu nýjan greiðslumáta</div>
        }
        <GridDeprecated base={9} marginTop={2}>
          {cards.map(({ id, maskedNumber, issuer, expiryMonth, expiryYear }, i) => (
            <Col col={4} colWide={3} colTablet={6} colMobile={12} key={id} marginBottom={0}>
              <Row>
                <Card
                  color={color}
                  ccnumber={maskedNumber.substring(maskedNumber.length - 8, maskedNumber.length)}
                  expiry={`${expiryMonth}/${expiryYear}`}
                  type={issuer}
                  buttonText={id === subscriptionPaymentMethodSavedPaymentId ? t('payment.selected') : t('payment.select')}
                  selected={id === subscriptionPaymentMethodSavedPaymentId}
                  onClick={() => {
                    updateSubscriptionPaymentMethod(
                      {
                        variables:
                        {
                          input:
                          {
                            subscriptionId: subId,
                            paymentInfo: {
                              paymentType: '4',
                              savedPaymentMethodId: id,
                            },
                          },
                        },
                        refetchQueries: ['subscriptionPaymentMethod'],
                      },
                    );
                  }}
                />
              </Row>
            </Col>
          ))}
        </GridDeprecated>
        {!showAdd && (
          <Button onClick={() => setShowAdd(true)} background={color} arrowRight>{t('payment.addButton')}</Button>
        )}
      </PaymentSection>
      {showAdd && (
        <PaymentSection
          title={t('payment.addTitle')}
          smallerTitle
          fullWidth
          noSpacingTop
          color={color}
        >
          <AddCard onComplete={() => setShowAdd(false)} authentication={authentication} />
        </PaymentSection>
      )}
    </>
  );
};

Payment.getInitalProps = () => {
  return {
    namespacesRequired: ['common'],
  };
};

export default inject('authentication')(Payment);
