import React, { useEffect, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { ErrorMessage } from '@hookform/error-message';
import {
  Box,
  Datepicker,
  FormStatusMessage,
  Grid,
  GridItem,
  Icon,
  Input,
  MainButton,
  Radio,
  Text,
} from '@nova-hf/ui';
import { getMaxLengthOfName } from 'beta/utils/helpers';
import MultiStepWrapper from 'containers/multiStepWrapper/MultiStepWrapper';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';
import { useSnackbar } from 'notistack';
import Authentication from 'store/authentication';
import Hradleid from 'store/hradleid';
import UI from 'store/ui';
import { IContext } from 'typings/context';
import { useTranslation } from 'utils/i18n';

import {
  useMeLazyQuery,
  usePayerAlterationsBatchMutation,
  useSubscriptionsQuery,
  WsPaymentMethod,
} from '../../../typings/graphql';

const COLOR = 'pink';

type PayerInfo = {
  email: string;
  address: string;
  city: string;
  zip: string;
  ssn: string;
  name: string;
};

type PayerAlterationForm = {
  newPayerPaysCurrentMonth: boolean;
  payerSsn: string;
  runDate: Date;
  salesNumber: string;
};

type PayerInfos = {
  [ssn: string]: PayerInfo;
};

type GreidandiProps = {
  hradleid: Hradleid;
  ui: UI;
  authentication: Authentication;
};

const Greidandi = ({ hradleid, authentication, ui }: GreidandiProps) => {
  const { t } = useTranslation(['multi']);
  const { enqueueSnackbar } = useSnackbar();
  const [payerInfos, setPayerInfos] = useState<PayerInfos>({});
  const [checkedSubs, setCheckedSubs] = useState<string[]>();
  const router = useRouter();
  const ssn = router?.query?.ssn;
  const { accountInput } = authentication;
  const { data } = useSubscriptionsQuery({
    variables: {
      subscriptionsInput: {
        onlyActive: true,
        forBulkMethods: true,
        perPage: 1000,
      },
      accountInput,
    },
    ssr: false,
  });

  const subscriptions = data?.me?.subscriptions?.subscriptions;
  const customerName = data?.me?.name;
  const [payerAlteration, { data: payerAlterationResults, loading: alterationLoading }] =
    usePayerAlterationsBatchMutation();
  const [getPayerInfo] = useMeLazyQuery({
    onCompleted(data) {
      if (data.me?.userProfile && data?.me?.email && data?.me?.ssn) {
        const ssn = data.me.ssn;
        setPayerInfos({
          [ssn]: {
            email: data?.me?.email || '',
            address: data?.me?.userProfile?.streetAddress || '',
            city: data?.me?.userProfile?.city || '',
            zip: data?.me?.userProfile?.postalCode || '',
            ssn: ssn,
            name: data?.me?.name || '',
          },
        });
      }
    },
  });

  const setPayerInfo = (payerSsn: string) => {
    getPayerInfo({ variables: { accountInput: { ssn: payerSsn } } });
  };

  const mapSubsToUsernamesAndInfo = () => {
    return hradleid?.subscriptionIds?.map((subId) => {
      const subscription = subscriptions?.find((sub) => sub?.subscriptionId === subId);
      const username = subscription?.name;
      const MAX = getMaxLengthOfName();
      const truncatedName =
        username && username.length > MAX ? `${username.slice(0, MAX)}...` : username;

      return {
        name: truncatedName as string,
        info: subscription?.accountName,
        id: subId,
        payerSsn: subscription?.accountSsn,
        payerName: subscription?.accountName,
        rateplanId: subscription?.rateplan?.id,
        ratePlanPreOrPost: subscription?.rateplan?.isPrepaid ? 'prepaid' : 'postpaid',
      };
    });
  };

  const mappedSubs = mapSubsToUsernamesAndInfo();
  const subsWhereCustomerIsNotPayer = mappedSubs?.filter((sub) => sub.payerSsn !== ssn);
  const filteredSubIds = subsWhereCustomerIsNotPayer?.map((sub) => sub.id);
  const getCheckedSubs = (subIds: Array<string>) => {
    setCheckedSubs(subIds);
  };

  const requestInput = mappedSubs
    ?.filter((request) => checkedSubs?.includes(request?.id))
    .map((request) => ({
      msisdn: request?.id,
      rateplanDetails: {
        rateplanPaymentTypeSnapShot: request?.rateplanId,
        rateplanSnapshot: request?.ratePlanPreOrPost,
      },
    }));

  const { control, watch, handleSubmit, setValue } = useForm<PayerAlterationForm>({
    defaultValues: {
      newPayerPaysCurrentMonth: false,
      payerSsn: '',
      runDate: undefined,
      salesNumber: '',
    },
    delayError: 500,
    mode: 'onChange',
  });

  const { payerSsn, newPayerPaysCurrentMonth, runDate, salesNumber } = watch();

  const onSubmit = async () => {
    if (subscriptions) {
      const usedInputsArray = [];
      for (const subscription of subscriptions) {
        const usedInput = requestInput?.find(
          (input) => input?.msisdn === subscription.subscriptionId,
        );
        if (usedInput) {
          usedInputsArray.push(usedInput);
        }
      }
      if (usedInputsArray.length) {
        try {
          const { data } = await payerAlteration({
            variables: {
              input: {
                info: {
                  newPayerPaysCurrentMonth: newPayerPaysCurrentMonth,
                  payer: {
                    method: WsPaymentMethod.BankClaim,
                    name: payerInfos[payerSsn].name,
                    ssn: payerInfos[payerSsn].ssn,
                    email: payerInfos[payerSsn].email,
                    address: {
                      address: payerInfos[payerSsn].address,
                      city: payerInfos[payerSsn].city,
                      postcode: payerInfos[payerSsn].zip,
                    },
                  },
                  runDate: runDate,
                  salesPerson: {
                    salesPersonNumber: Number(salesNumber),
                  },
                },
                requests: usedInputsArray,
              },
            },
          });
          if (data?.payerAlterationsBatch?.every((i) => i.success)) {
            ui?.setHasMultiMenu(false);
            enqueueSnackbar('Beiðnir verða framkvæmdar innan skamms', {
              variant: 'success',
            });
            await router.push({
              pathname: `/${ssn}/fjoldaskraning`,
              query: { ssn: ssn },
            });
          } else {
            enqueueSnackbar('Ekki tókst að senda allar breytingar. Sjá niðurstöður', {
              variant: 'error',
            });
          }
        } catch (e) {
          enqueueSnackbar('Upp kom villa við að senda beiðni', {
            variant: 'error',
          });
        }
      }
    }
  };

  useEffect(() => {
    if (payerSsn?.length === 10) {
      setPayerInfo(payerSsn);
    }
  }, [payerSsn]);

  return (
    <MultiStepWrapper
      hradleid={hradleid}
      color={COLOR}
      getMappedSubs={mappedSubs}
      disabledSubIds={filteredSubIds ?? []}
      sendCheckedToChild={getCheckedSubs}
      title={t('headers.payerChange')}
      firstRowTitle={t('headers.user')}
      secondRowTitle={t('headers.payer')}
      icon="transfer"
      customerName={customerName ?? ''}
      needsBiggerWidth={true}
    >
      <Box display="flex" flexDirection="column" gap={3}>
        <Text color="black100" variant="h4">
          {t('payer.choose')}
        </Text>
        <Text color="black100">{t('payer.subtitle')}</Text>

        <Box renderAs="form" onSubmit={handleSubmit(onSubmit)}>
          <Grid gridTemplate={{ sm: 4, md: 8 }}>
            <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
              <Controller
                name="payerSsn"
                control={control}
                rules={{
                  required: true,
                  maxLength: {
                    value: 10,
                    message: 'Kennitala getur ekki verið lengri en 10 stafir',
                  },
                  minLength: {
                    value: 10,
                    message: 'Kennitala getur ekki verið styttri en 10 stafir',
                  },
                }}
                render={({ field, formState: { errors } }) => {
                  const { value, name, ref } = field;
                  return (
                    <Box>
                      <Input
                        id="payerSsn"
                        name="payerSsnInput"
                        label="Kennitala"
                        isBold={false}
                        value={value}
                        ref={ref}
                        onChange={(e) => setValue('payerSsn', e?.target?.value)}
                      />
                      <ErrorMessage
                        errors={errors}
                        name={name}
                        render={() => <FormStatusMessage message="Villa" status="error" />}
                      />
                    </Box>
                  );
                }}
              />
            </GridItem>
            <GridItem gridColumn={{ sm: 'span2', md: 'span4' }}>
              <Controller
                name="runDate"
                control={control}
                rules={{ required: true }}
                render={() => {
                  return (
                    <>
                      <Datepicker
                        inputId="datepicker"
                        inputName="datepicker"
                        color="black100"
                        selected={runDate}
                        minDate={new Date()}
                        onSelect={(date: Date) => setValue('runDate', date)}
                      />
                    </>
                  );
                }}
              />
            </GridItem>
            <GridItem gridColumn={{ sm: 'span2', md: 'span4' }}>
              <Controller
                name="salesNumber"
                control={control}
                rules={{
                  required: true,
                }}
                render={({ field, formState: { errors } }) => {
                  const { value, name, ref } = field;
                  return (
                    <Box>
                      <Input
                        id="salesNumber"
                        name="salesNumberInput"
                        label="Sölunúmer"
                        isBold={false}
                        value={value}
                        ref={ref}
                        onChange={(e) => setValue('salesNumber', e.target.value)}
                      />
                      <ErrorMessage
                        errors={errors}
                        name={name}
                        render={() => <FormStatusMessage message="Villa" status="error" />}
                      />
                    </Box>
                  );
                }}
              />
            </GridItem>
            <GridItem gridColumn={{ sm: 'span2', md: 'span4' }}>
              <Controller
                name="newPayerPaysCurrentMonth"
                control={control}
                render={() => {
                  return (
                    <>
                      <Radio
                        isChecked={newPayerPaysCurrentMonth}
                        value="Nýr greiðandi borgar núverandi tímabil"
                        color={COLOR}
                        onChange={() => setValue('newPayerPaysCurrentMonth', true)}
                      />
                      <Radio
                        isChecked={!newPayerPaysCurrentMonth}
                        value="Nýr greiðandi tekur við á næsta tímabili"
                        color={COLOR}
                        onChange={() => setValue('newPayerPaysCurrentMonth', false)}
                      />
                    </>
                  );
                }}
              />
            </GridItem>
            <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
              <Box
                display="flex"
                marginTop={6}
                justifyContent="flex-end"
                flexDirection={{ sm: 'column', md: 'row' }}
              >
                <Box display="flex" width={{ sm: '100%', md: '4/12' }}>
                  <MainButton
                    text={'Breyta'}
                    colorScheme={COLOR}
                    isDisabled={!payerSsn || !runDate || !salesNumber}
                    isSubmitButton
                    isLoading={alterationLoading}
                  />
                </Box>
              </Box>
            </GridItem>
          </Grid>
        </Box>
        {filteredSubIds && filteredSubIds.length > 0 && (
          <Box display="flex" flexDirection="row" alignItems="center" gap={1}>
            <Icon icon="info" color="warning" />
            <Text>{t('multi:multi.payerError')}</Text>
          </Box>
        )}
        {payerAlterationResults?.payerAlterationsBatch?.map((r) => (
          <Text color="warning" key={r.requestId}>
            {r.requestId} {r.message}
          </Text>
        ))}
      </Box>
    </MultiStepWrapper>
  );
};

Greidandi.getInitialProps = ({ pathname, query }: IContext) => {
  return {
    pathname,
    ssn: query.ssn,
    namespacesRequired: ['multi'],
  };
};

export default inject('hradleid', 'authentication', 'ui')(observer(Greidandi));
