import * as React from 'react';
import { useMutation, useQuery } from '@apollo/client';
import {
  Button,
  CheckboxDeprecated,
  Col,
  ErrorMessage,
  FormDropdown,
  Payment,
  PaymentSection,
  Row,
} from '@nova-hf/ui';
import LinkWrapper from 'components/link-wrapper/LinkWrapper';
import { CHANGE_SUBSCRIPTION_RATEPLAN } from 'graphql/mutations/rateplan';
import { CARDS } from 'graphql/queries/cards';
import { ALLRATEPLANS } from 'graphql/queries/rateplans';
import { SUBSCRIPTIONACCOUNT } from 'graphql/queries/subscriptionAccount';
import { inject } from 'mobx-react';
import Link from 'next/link';
import { useSnackbar } from 'notistack';
import { IProfile, IRateplanCategory, IUserData } from 'typings';
import { formatPrice, isCompany, isStringPhoneNumber, profileColor } from 'utils/helpers';
import { useTranslation } from 'utils/i18n';

import {
  useCustomerHasFiberQuery,
  useCustomerIdByNationalIdQuery,
  useIsEligibleForNetNetQuery,
} from '../../../../typings/graphql';
import Settings from '../../containers/settings/Settings';

import { SUBSCRIPTION_PLAN } from './queries/thjonustuleid';

interface IProps {
  subscription: IProfile;
  color: string;
  authentication?: any;
}
interface ITjonustuleidProps {
  subscriptionId: string;
  authentication?: any;
}
interface IPlanProps extends IProps {
  change?: any;
  allowedToChange: boolean;
}

interface IPaymentsProps {
  onSelectCard: any;
  onSelectPaymentType: any;
  selectedPaymentType: string;
  authentication?: any;
  color: string;
}

const Plan = ({ subscription, color, allowedToChange, authentication }: IPlanProps) => {
  const { accountInput, isStaff } = authentication;
  const { rateplan, subscriptionId } = subscription;
  const [changeSubscriptionRateplan] = useMutation(CHANGE_SUBSCRIPTION_RATEPLAN);
  const { loading, error, data } = useQuery<IRateplanCategory>(ALLRATEPLANS);
  const { data: subscriptionData } = useQuery<IUserData>(SUBSCRIPTIONACCOUNT, {
    variables: { subscriptionId, accountInput, servicesRequired: false },
  });
  const { data: contractCustomerData, error: contractCustomerError } =
    useCustomerIdByNationalIdQuery({
      variables: {
        input: {
          nationalId: subscriptionData?.me?.ssn,
        },
      },
      skip: !subscriptionData?.me?.ssn,
    });
  const { data: hasFiberData } = useCustomerHasFiberQuery({
    variables: {
      input: {
        ssn: subscriptionData?.me?.ssn ?? '',
      },
    },
    skip: !subscriptionData?.me?.ssn,
  });

  const { data: fiberData } = useIsEligibleForNetNetQuery({
    variables: {
      input: {
        id: contractCustomerData?.customerByNationalId?.id,
      },
    },
    skip: contractCustomerError !== undefined || !contractCustomerData?.customerByNationalId?.id,
  });

  const hasFiber =
    hasFiberData?.isPayerOrUserOfFiber === true || fiberData?.isEligibleForNetNet === true;

  const { enqueueSnackbar } = useSnackbar();
  const { t } = useTranslation('stillingar');

  const [selectedRateplanId, setCurrRateplan] = React.useState('');
  const [selectedServicepackId, setCurrServicepack] = React.useState('');
  const [card, setCard] = React.useState('');
  const [paymentType, setPaymentType] = React.useState('card');
  const [message, setMessage] = React.useState('');
  const [loadingButton, setLoading] = React.useState(false);
  const [activateNextMonth, setActivateNextMonth] = React.useState(false);

  const onSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setMessage('');

    if (!selectedRateplanId) {
      setMessage(t('plan.errorMessage'));
      return;
    }

    try {
      setLoading(true);

      const res = await changeSubscriptionRateplan({
        variables: {
          subscriptionId,
          input: {
            rateplanId: selectedRateplanId,
            paymentId: paymentType === 'card' ? card : null,
            servicepackId: selectedServicepackId,
            paymentType,
            activateNextMonth,
          },
        },
        refetchQueries: [{ query: SUBSCRIPTION_PLAN, variables: { subscriptionId, accountInput } }],
        awaitRefetchQueries: true,
      });

      setLoading(false);

      if (res.data.changeSubscriptionRateplan.error) {
        throw new Error(res.data.changeSubscriptionRateplan.error.message);
      } else {
        enqueueSnackbar(t('plan.successMessage'), {
          variant: 'success',
        });
        setCurrServicepack('');
        setCurrRateplan('');
        setCard('');
        setPaymentType('card');
        setActivateNextMonth(false);
      }
    } catch (e: any) {
      enqueueSnackbar(t('plan.error', { error: e.message }), {
        variant: 'error',
      });
      setMessage(e.message);
      setLoading(false);
    }
  };

  if (loading || error || !data) {
    return <div>{'Sæki...'}</div>;
  }

  const category = rateplan.availableRateplans[0];
  const dislplayRateplans = isStaff
    ? category?.rateplans.filter((r) => (!hasFiber ? r.id !== 'R1706' : r.id))
    : category?.rateplans.filter((r) => (!hasFiber ? !r.isVip : !r.isVip || r.id === 'R1706'));

  const rateplans = data?.rateplans;
  const selectedRateplan = rateplans?.find((r) => r.id === selectedRateplanId);
  const servicepacks =
    selectedRateplan?.id === 'R2088' &&
    selectedRateplan?.availableServicepacks.find((s) => s.servicepackType === 'phonedata');

  // payment required if rateplan change from prepaid -> postpaid else if postpaid -> postpaid existing payment method is used
  const needsPayment = rateplan.isPrepaid && selectedRateplan && !selectedRateplan.isPrepaid;
  // only allow activate next month if rateplan change from postpaid -> postpaid

  const disabled =
    !selectedRateplanId ||
    (needsPayment && !card && paymentType !== 'bank') ||
    (servicepacks && !selectedServicepackId);

  const onSelect = (rateplanId: string) => {
    setCurrRateplan(rateplanId);
    setCurrServicepack('');
  };

  const accountSsn = subscriptionData?.me?.profiles[0]?.accountSsn;
  const payerIsCompany = accountSsn ? isCompany(accountSsn) : false;

  return (
    <>
      <p>
        {t('plan.current')} <strong>{rateplan.title}</strong>
      </p>

      {/* TODO: move text to contentful */}
      {rateplan.id === 'R1150' && <div>{t('plan.descriptionHraðleið')}</div>}

      {dislplayRateplans && allowedToChange && (
        <form onSubmit={onSubmit}>
          {message && <ErrorMessage>{message}</ErrorMessage>}
          <Row>
            <Col col={servicepacks ? 6 : 12}>
              <FormDropdown onSelect={onSelect} label={t('plan.choosePlan')}>
                {dislplayRateplans
                  .filter((item) => payerIsCompany || !item.isVip || item.id === 'R1706')
                  .map(({ id, title }) => (
                    <option key={id} value={id}>
                      {title}
                    </option>
                  ))}
              </FormDropdown>
            </Col>
            {servicepacks && (
              <Col col={6}>
                <FormDropdown
                  onSelect={(servicepackId: string) => setCurrServicepack(servicepackId)}
                  label={t('plan.chooseData')}
                >
                  {servicepacks?.servicepacks
                    .filter((s) => s.forSale)
                    .map(({ title, price, id }) => (
                      <option key={id} value={id}>
                        {title} - {formatPrice(price)}
                      </option>
                    ))}
                </FormDropdown>
              </Col>
            )}
            <Col col={6}>
              <CheckboxDeprecated
                color={color}
                name="activateNextMonth"
                checked={activateNextMonth}
                onChange={(e: { target: { checked: boolean } }) =>
                  setActivateNextMonth(e.target.checked)
                }
              >
                {t('plan.activateNextMonth')}
              </CheckboxDeprecated>
            </Col>
            {needsPayment && (
              <Payments
                onSelectCard={(cardId: string) => setCard(cardId)}
                onSelectPaymentType={(e: { target: { checked: boolean } }) =>
                  setPaymentType(e.target.checked ? 'bank' : 'card')
                }
                selectedPaymentType={paymentType}
                authentication={authentication}
                color={color}
              />
            )}
            <Col col={6} push={6}>
              <Button
                loading={loadingButton}
                onSelect={onSubmit}
                disabled={disabled}
                fill
                arrowRight
                background={color}
              >
                {t('plan.button')}
              </Button>
            </Col>
          </Row>
        </form>
      )}
    </>
  );
};

const Cancel = ({ subscription, color, authentication }: IProps) => {
  const { subscriptionId, title } = subscription;
  const isPhoneNumber = isStringPhoneNumber(title);
  const rateplanTitle = subscription?.rateplan?.title;
  const usedTitle = isPhoneNumber ? rateplanTitle?.toLowerCase() : title;
  const { accountInput } = authentication;
  const { t } = useTranslation('stillingar');

  return (
    <Button
      linkComponent={
        <LinkWrapper href={`/${accountInput.ssn}/thjonusta/${subscriptionId}/uppsogn`} />
      }
      outline={color}
      background="white"
      text={color}
    >
      {isPhoneNumber
        ? t('plan.cancelPhoneNumber', { subscriptionTitle: usedTitle })
        : t('plan.cancelService', { subscriptionTitle: usedTitle })}
    </Button>
  );
};

const Payments = ({
  onSelectCard,
  onSelectPaymentType,
  authentication,
  color,
  selectedPaymentType,
}: IPaymentsProps) => {
  const { accountInput, isStaff } = authentication;
  const { loading, error, data } = useQuery<IUserData>(CARDS, { variables: { accountInput } });
  const { t } = useTranslation('stillingar');

  if (loading || error || !data) {
    return <div>{t('plan.payments.loading')}</div>;
  }
  const cards = data?.me?.cards;

  const subtitle = (
    <>
      {t('plan.payments.subtitle')}&nbsp;
      <Link
        href={{
          pathname: '/stillingar/payment',
          query: isStaff && { ssn: accountInput.ssn },
        }}
        target="_blank"
        onClick={() => isStaff && authentication.setAccountInput(accountInput.ssn)}
      >
        {t('plan.payments.linkTitle')}
      </Link>
    </>
  );

  return (
    <PaymentSection title={t('plan.payments.title')} subtitle={subtitle} smallerTitle fullWidth>
      {selectedPaymentType !== 'bank' && cards?.length > 0 && (
        <FormDropdown onSelect={onSelectCard} label={t('plan.payments.chooseCard')}>
          {cards?.map(({ id, maskedNumber, issuer }) => (
            <option key={id} value={id}>
              {issuer} - {maskedNumber.substring(maskedNumber.length - 8, maskedNumber.length)}
            </option>
          ))}
        </FormDropdown>
      )}
      <CheckboxDeprecated
        color={color}
        name="allowMarketing"
        checked={selectedPaymentType === 'bank'}
        onChange={onSelectPaymentType}
      >
        {t('plan.payments.bank')}
      </CheckboxDeprecated>
    </PaymentSection>
  );
};

const Thjonustuleid = ({ subscriptionId, authentication }: ITjonustuleidProps) => {
  const { accountInput, isStaff } = authentication;
  const { loading, error, data } = useQuery<IUserData>(SUBSCRIPTION_PLAN, {
    variables: { subscriptionId, accountInput },
  });
  const { t } = useTranslation('stillingar');

  const subscription = data?.me.subscriptions.subscriptions[0];
  const color = (subscription?.rateplan && profileColor(subscription?.rateplan)) ?? 'pink';
  const allowedToChange = isStaff || subscription?.isPayer;

  const subscriptionTitle = subscription?.title ?? '';
  const isPhoneNumber = isStringPhoneNumber(subscriptionTitle);
  const rateplanTitle = subscription?.rateplan?.title;
  const usedTitle = isPhoneNumber ? rateplanTitle?.toLowerCase() : subscriptionTitle;

  if (!subscription) return null;
  return (
    <Settings subscriptionId={subscriptionId}>
      <Payment noContainer>
        <PaymentSection smallerTitle fullWidth noSpacingTop title={t('plan.title')}>
          {loading || error ? (
            <div>...</div>
          ) : (
            <Plan
              subscription={subscription}
              color={color}
              authentication={authentication}
              allowedToChange={allowedToChange}
            />
          )}
        </PaymentSection>
      </Payment>
    </Settings>
  );
};

Thjonustuleid.getInitialProps = ({ query }: any) => {
  return {
    subscriptionId: query.subscriptionId,
    namespacesRequired: ['stillingar'],
  };
};

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