import React, { FormEvent, useState } from 'react';
import { inject } from 'mobx-react';
import { useRouter } from 'next/router';

import {
  NumberTextBox,
  Button,
  Summary,
  SummaryItem,
  Payment,
  PaymentSection,
  PaymentForm,
  PaymentFooter,
  CreditCard,
  ErrorMessage,
  ContainerDeprecated,
  CloseArrow,
} from '@nova-hf/ui';

import { IClaim, ITransaction } from 'typings';
import { formatDate, formElementsToObject } from 'utils/helpers';
import { useTranslation } from 'utils/i18n';

import Wrapper from 'components/app-layout/Wrapper';
import UI from 'store/ui';
import Claims from 'store/claims';
import Authentication from 'store/authentication';
import { PaymentMethodInput, usePayClaimsMutation } from 'typings/graphql';

interface IGreidaProps {
  ui?: UI;
  claims?: Claims;
  authentication?: Authentication;
}

const cleanPaymentInput = ({ cardNumber, ssn, ...rest }: PaymentMethodInput) => ({
  cardNumber: cardNumber.replace(/\s/g, ''),
  ssn: ssn.replace('-', ''),
  ...rest,
});

const Greida = ({ claims, authentication, ui }: IGreidaProps) => {
  if (!authentication || !claims || !ui) return null;

  const [invalid, setInvalid] = useState('');
  const [message, setMessage] = useState('');

  const router = useRouter();
  const { t } = useTranslation('invoices');

  const [payClaims, { loading }] = usePayClaimsMutation();

  const {
    accountInput: { ssn },
  } = authentication;

  const { pageColor } = ui;

  const { selectedClaims, totalCharge } = claims;

  const onSubmit = async (e: FormEvent<HTMLFormElement>) => {
    setMessage('');

    e.preventDefault();
    const formInputs = Object.values(e.currentTarget.elements) as HTMLInputElement[];

    if (!e.currentTarget.checkValidity()) {
      const firstInvalid = formInputs.find((el) => !el.validity.valid);

      if (firstInvalid) {
        setInvalid(firstInvalid.name);

        firstInvalid.focus();
      }
      return;
    }

    setInvalid('');

    const paymentInfo = formElementsToObject(
      e.currentTarget.elements as HTMLCollectionOf<HTMLInputElement>,
    ) as PaymentMethodInput;

    const claimsList = selectedClaims.map(({ claimNumber, dueDate, totalCharge }: IClaim) => ({
      claimNumber,
      dueDate,
      amount: totalCharge,
    }));

    try {
      const { data } = await payClaims({
        variables: {
          input: {
            paymentInfo: cleanPaymentInput(paymentInfo),
            claims: claimsList,
            ssn,
          },
        },
      });

      if (data?.payClaims.error) {
        setMessage(data?.payClaims.error.message);
      } else {
        claims.transaction = data?.payClaims.transaction as ITransaction;

        router
          .push({ pathname: `/${ssn}/reikningar/greida/takk` })
          .then(() => window.scrollTo(0, 0));
      }
    } catch (e) {
      setMessage(`${t('paymentSection.errorMessage')}: ${e}`);
    }
  };

  const onPrev = () => {
    router.back();
  };

  return (
    <Wrapper header="none" noFooter>
      <ContainerDeprecated>
        <Payment
          onSubmit={(e: FormEvent<HTMLFormElement>) => {
            onSubmit(e);
          }}
        >
          <PaymentSection smaller title={t('paymentSection.summary')}>
            <Summary nowTotal={totalCharge} showZeroPrice itemHeader={t('invoices')}>
              {selectedClaims &&
                selectedClaims.map((claim: IClaim) => (
                  <SummaryItem
                    key={claim.claimNumber}
                    title={formatDate(claim.dueDate, 'd. MMMM yyyy')}
                    priceNow={claim.totalCharge}
                    showTotalValue
                  />
                ))}
            </Summary>
          </PaymentSection>
          <PaymentSection smaller title={t('paymentSection.paymentMethod')}>
            <PaymentForm>
              <NumberTextBox
                data-key="ssn"
                label={t('paymentSection.ssn')}
                name="cardholder-ssn"
                autoComplete="false"
                errorType="ssn"
                status={invalid === 'cardholder-ssn' ? 'error' : ''}
                ssn
                required
              />
              <NumberTextBox
                data-key="cardNumber"
                label={t('paymentSection.cardnumber')}
                name="cc-number"
                autoComplete="cc-number"
                errorType="cc"
                status={invalid === 'cc-number' ? 'error' : ''}
                cc
                required
              />
              <CreditCard>
                <NumberTextBox
                  data-key="expiryMonth"
                  label={t('paymentSection.month')}
                  name="cc-exp-month"
                  autoComplete="cc-exp-month"
                  maxLength="2"
                  status={invalid === 'cc-exp-month' ? 'error' : ''}
                  errorType="mm"
                  required
                />
                <NumberTextBox
                  data-key="expiryYear"
                  label={t('paymentSection.year')}
                  name="cc-exp-year"
                  autoComplete="cc-exp-year"
                  length="2"
                  status={invalid === 'cc-exp-year' ? 'error' : ''}
                  errorType="yy"
                  required
                />
                <NumberTextBox
                  data-key="cvc"
                  label={t('paymentSection.cvc')}
                  name="cc-exp-csc"
                  autoComplete="cc-exp-csc"
                  length="3"
                  status={invalid === 'cc-exp-csc' ? 'error' : ''}
                  errorType="cvc"
                  required
                />
              </CreditCard>
            </PaymentForm>
            {message !== '' && <ErrorMessage>{message}</ErrorMessage>}
            <PaymentFooter>
              <PaymentForm onecolumn>
                <Button big fill background={pageColor} type="submit" loading={loading}>
                  {t('claims.pay')}
                </Button>
              </PaymentForm>
            </PaymentFooter>
          </PaymentSection>
          <CloseArrow dark onClick={onPrev} />
        </Payment>
      </ContainerDeprecated>
    </Wrapper>
  );
};

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

export default inject('ui', 'claims', 'authentication')(Greida);
