import * as React from 'react';
import Router from 'next/router';
import { observable, makeObservable } from 'mobx';
import { observer, inject } from 'mobx-react';
import { set } from 'lodash';
import {
  NumberTextBox,
  Button,
  Payment,
  PaymentSection,
  PaymentForm,
  CreditCard,
  ErrorMessage,
} from '@nova-hf/ui';
import { Mutation } from '@apollo/client/react/components';
import { withSnackbar, WithSnackbarProps } from 'notistack';

import { IAutoRefill } from 'typings';
import DateSVG from 'assets/svg/date.svg';

import { formatDate } from 'utils/helpers';
import { WithTranslation, withTranslation } from 'utils/i18n';
import { CHANGE_AUTOREFILL_PAYMENT, CHANGE_AUTOREFILL } from 'graphql/mutations/autorefills';

import { ProfileConfirmation } from 'components/profile-detail/ProfileConfirmation';

import Change from 'store/change';

interface IChangeAutoRefillProps extends WithTranslation, WithSnackbarProps {
  change?: Change;
  color: string;
  subscriptionId: string;
  returnLink: string;
}

interface IConfirmChangeState {
  message: string;
  status: string;
}

class ChangeAutoRefill extends React.Component<IChangeAutoRefillProps, IConfirmChangeState> {
  invalid = '';

  forms: Array<HTMLFormElement> = [];

  state: IConfirmChangeState = {
    message: '',
    status: '',
  };

  onChangePayment = async (
    e: React.FormEvent<HTMLFormElement>,
    changeAutoRefillPaymentInfo: any,
  ) => {
    const { t, subscriptionId, change, returnLink, enqueueSnackbar } = this.props;
    const payload: any = {};

    if (!change) return;

    this.setState({ status: '', message: '' });

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

      const firstInvalid: any = formInputs.find((el) => !el.validity.valid);

      if (firstInvalid) {
        this.invalid = firstInvalid.name;
        firstInvalid.focus();
      }
      return;
    }
    this.invalid = '';
    this.forms.forEach((f) => {
      if (f) {
        Object.entries(f.value as string).forEach(([key, value]) => {
          set(payload, key.split('.'), value);
        });
      }
    });

    try {
      const { data } = await changeAutoRefillPaymentInfo({
        variables: { input: { paymentInfo: payload.paymentInfo, subscriptionId } },
      });

      if (data?.changeAutoRefillPaymentInfo?.error) {
        this.setState({
          status: 'error',
          message: data?.changeAutoRefillPaymentInfo?.error.message,
        });
        return;
      }

      enqueueSnackbar(t('common:notification.success'), {
        variant: 'success',
      });

      change.resetChangeFlow();
      Router.push(returnLink).then(() => window.scrollTo(0, 0));
    } catch (e) {
      this.setState({
        status: 'error',
        message: `${t('detail.paymentSection.errorMessage')}: ${e}`,
      });
    }
  };

  onChangeRefillDate = async (changeAutoRefill: any, autoRefill?: IAutoRefill) => {
    const { t, subscriptionId, change, returnLink, enqueueSnackbar } = this.props;
    if (!change) return;

    const input = {
      refillId: autoRefill && autoRefill.refillId,
      activateMonthly: true,
    };

    try {
      const { data } = await changeAutoRefill({ variables: { input, subscriptionId } });

      if (data?.changeAutoRefill?.error) {
        this.setState({ message: data?.changeAutoRefill?.error.message });

        return;
      }

      enqueueSnackbar(t('common:notification.success'), {
        variant: 'success',
      });

      change.resetChangeFlow();
      Router.push(returnLink).then(() => window.scrollTo(0, 0));
    } catch (e) {
      this.setState({ message: t('detail.errorMessage') });
    }
  };

  constructor(props: IChangeAutoRefillProps) {
    super(props);

    makeObservable(this, {
      invalid: observable,
    });
  }

  renderDate(color: string, autoRefill: IAutoRefill) {
    const { t } = this.props;
    const { message } = this.state;

    return (
      <Mutation mutation={CHANGE_AUTOREFILL}>
        {(changeAutoRefill: any, { loading }: any) => {
          return (
            <ProfileConfirmation
              color={color}
              title={t('detail.date.title')}
              description={t('detail.date.description', {
                date: formatDate(autoRefill.nextRefill, 'dd.MM.yyyy'),
              })}
              icon={<DateSVG />}
              errorMessage={message}
              buttonLoading={loading}
              buttonText={t('detail.cancel.confirmation.button')}
              onClick={() => {
                this.onChangeRefillDate(changeAutoRefill, autoRefill);
              }}
              posCenter
            />
          );
        }}
      </Mutation>
    );
  }

  renderPayment(color: string, autorefill: IAutoRefill) {
    const { t } = this.props;
    const { message } = this.state;

    return (
      <Mutation mutation={CHANGE_AUTOREFILL_PAYMENT}>
        {(changeAutoRefillPaymentInfo: any, { loading }: any) => {
          return (
            <Payment
              onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
                this.onChangePayment(e, changeAutoRefillPaymentInfo);
              }}
              fullWith
            >
              <PaymentSection
                title={t('detail.paymentSection.paymentMethod')}
                smaller
                fullWidth
                noSpacingTop
                smallerTitle
              >
                {autorefill && (
                  <p>
                    {t('detail.paymentSection.currentCard')}:{' '}
                    {autorefill.paymentMethod.maskedCardNumber}
                  </p>
                )}
                <PaymentForm ref={(el: any) => (this.forms[1] = el)}>
                  <NumberTextBox
                    data-key="paymentInfo.cardNumber"
                    label={t('detail.paymentSection.cardnumber')}
                    name="cc-number"
                    autoComplete="cc-number"
                    errorType="cc"
                    status={this.invalid === 'cc-number' ? 'error' : ''}
                    cc
                    required
                  />
                  <CreditCard>
                    <NumberTextBox
                      data-key="paymentInfo.expiryMonth"
                      label={t('detail.paymentSection.month')}
                      name="cc-exp-month"
                      autoComplete="cc-exp-month"
                      maxLength="2"
                      status={this.invalid === 'cc-exp-month' ? 'error' : ''}
                      errorType="mm"
                      required
                    />
                    <NumberTextBox
                      data-key="paymentInfo.expiryYear"
                      label={t('detail.paymentSection.year')}
                      name="cc-exp-year"
                      autoComplete="cc-exp-year"
                      length="2"
                      status={this.invalid === 'cc-exp-year' ? 'error' : ''}
                      errorType="yy"
                      required
                    />
                    <NumberTextBox
                      data-key="paymentInfo.cvc"
                      label={t('detail.paymentSection.cvc')}
                      name="cc-exp-csc"
                      autoComplete="cc-exp-csc"
                      length="3"
                      status={this.invalid === 'cc-exp-csc' ? 'error' : ''}
                      errorType="cvc"
                      required
                    />
                  </CreditCard>
                  <NumberTextBox
                    data-key="paymentInfo.ssn"
                    label={t('detail.paymentSection.ssn')}
                    name="cardholder-ssn"
                    autoComplete="false"
                    errorType="ssn"
                    status={this.invalid === 'cardholder-ssn' ? 'error' : ''}
                    ssn
                    required
                  />
                </PaymentForm>
                {message !== '' && <ErrorMessage>{message}</ErrorMessage>}
                <PaymentForm onecolumn>
                  <Button fill background={color} type="submit" loading={loading}>
                    {t('detail.cancel.confirmation.button')}
                  </Button>
                </PaymentForm>
              </PaymentSection>
              <div />
            </Payment>
          );
        }}
      </Mutation>
    );
  }

  render() {
    const { change, color } = this.props;
    if (!change) return;

    const { autoRefillToChange, autoRefillType } = change;

    if (!autoRefillToChange) return;

    switch (autoRefillType) {
      case 'date':
        return this.renderDate(color, autoRefillToChange);
      case 'payment':
        return this.renderPayment(color, autoRefillToChange);
      default:
        return <div>Villa!</div>;
    }
  }
}

export default withTranslation(['subscription', 'common'])(
  withSnackbar(inject('change')(observer(ChangeAutoRefill))),
);
