import * as React from 'react';
import { useEffect } from 'react';
import { useApolloClient, useMutation, useQuery } from '@apollo/client';
import {
  Box,
  Button,
  CheckboxDeprecated,
  Col,
  Dialog,
  MainButton,
  ModalHeader,
  NumberTextBox,
  Payment,
  PaymentForm,
  PaymentSection,
  Row,
  SecondaryButton,
  Text,
  TextBox,
} from '@nova-hf/ui';
import { getFeatureFlags } from 'beta/components/feature-flags/FeatureFlags';
import { UPDATE_SUBSCRIPTION } from 'graphql/mutations/subscription';
import { KENNITALA } from 'graphql/queries/kennitala';
import { SUBSCRIPTIONUSER } from 'graphql/queries/subscriptionUser';
import { inject } from 'mobx-react';
import { useRouter } from 'next/router';
import { useSnackbar } from 'notistack';
import { IUserData } from 'typings';
import {
  useChangePhoneNumberRightHolderMutation,
  useCustomerNameByNationalIdLazyQuery,
  usePhoneNumberRightHolderQuery,
} from 'typings/graphql';
import { WithTranslation, withTranslation } from 'utils/i18n';

import Settings from '../../containers/settings/Settings';

interface IProps extends WithTranslation {
  subscriptionId?: any;
  subscriptionIds?: string[];
  color?: string;
  ui?: any;
}

interface IUserProps extends IProps {
  profileData: any;
  isStaff: boolean;
}

interface IPageProps extends IProps {
  query: any;
  authentication?: any;
}

const UserData: React.FunctionComponent<IUserProps> = (props) => {
  const featureFlags = getFeatureFlags();
  const isRightHolderFlagActive = featureFlags['retthafi'];
  const { enqueueSnackbar } = useSnackbar();
  const router = useRouter();
  const { t, profileData, color, isStaff } = props;
  const subscriptionId = props?.subscriptionId ?? undefined;
  const subscriptionIds = props?.subscriptionIds ?? undefined;
  const [updateSubscription] = useMutation(UPDATE_SUBSCRIPTION);
  const client = useApolloClient();

  const [profile, setProfile] = React.useState(profileData);
  const [inputData, setInputData] = React.useState(profileData);
  const [status, setStatus] = React.useState('');
  const [message, setMessage] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [showModal, setShowModal] = React.useState(false);
  const [isRightHolder, setIsRightHolder] = React.useState(false);
  const [rightHolderName, setRightHolderName] = React.useState('');

  if (!profile && !inputData) return null;

  const isFiber = profile?.rateplan?.typeId === 'fiber';
  const isBundle = subscriptionId?.length !== 7 && !subscriptionIds;

  const isNewData =
    inputData.name !== profile.name ||
    inputData.ssn !== profile.ssn ||
    inputData.allowMarketing !== profile.allowMarketing ||
    inputData.isVisibleInPhonebook !== profile.isVisibleInPhonebook ||
    inputData.phoneNumber !== profile.phoneNumber ||
    subscriptionIds;

  const setNewValue = (
    newValue: string | boolean,
    key: 'name' | 'ssn' | 'allowMarketing' | 'isVisibleInPhonebook' | 'phoneNumber',
  ) => {
    setInputData({
      ...inputData,
      [key]: newValue,
    });
  };

  const {
    data: phoneNumberRightHolderData,
    error: phonenumberRightHolderError,
    refetch: phoneNumberRightHolderRefetch,
  } = usePhoneNumberRightHolderQuery({
    variables: {
      input: {
        phoneNumber: profile.phoneNumber,
      },
    },
  });

  const rightHolderNationalId = phoneNumberRightHolderData?.phoneNumberRightHolder?.nationalId;

  const [getCustomerName] = useCustomerNameByNationalIdLazyQuery({
    onCompleted(data) {
      if (data.customerByNationalId?.name) setRightHolderName(data.customerByNationalId.name);
    },
  });

  const [changePhoneNumberRightHolder] = useChangePhoneNumberRightHolderMutation({
    onCompleted() {
      phoneNumberRightHolderRefetch();
    },
    onError(error) {
      if (error instanceof Error) {
        enqueueSnackbar(t('user.errorChangeRightHolder'), {
          variant: 'error',
        });
      }
    },
  });

  useEffect(() => {
    if (profile.ssn === rightHolderNationalId) {
      setIsRightHolder(true);
    } else {
      getCustomerName({
        variables: { input: { nationalId: rightHolderNationalId } },
      });
    }
  }, [rightHolderNationalId]);

  const changeRightHolder = async () => {
    await changePhoneNumberRightHolder({
      variables: {
        input: {
          phoneNumber: profile.phoneNumber,
          rightHolderNationalId: rightHolderNationalId,
          newRightHolderNationalId: profile.ssn,
        },
      },
    });
  };

  const cancelChanges = () => {
    setInputData({
      name: profile.name,
      ssn: profile.ssn,
      allowMarketing: profile.allowMarketing,
      isVisibleInPhonebook: profile.isVisibleInPhonebook,
      phoneNumber: profile.phoneNumber,
    });
    setMessage('');
    setStatus('');
  };

  const onChangeSsn = async (ssn: string) => {
    setNewValue(ssn, 'ssn');
    setStatus('');
    setMessage('');

    if (ssn.length === 10) {
      try {
        const { data } = await client.query({
          query: KENNITALA,
          variables: { ssn },
        });

        const {
          kennitala: { name },
        } = data;

        setInputData({
          name,
          ssn,
          allowMarketing: inputData.allowMarketing,
          isVisibleInPhonebook: inputData.isVisibleInPhonebook,
          phoneNumber: inputData.phoneNumber,
        });
      } catch (e) {
        setStatus('error');
        setMessage(`Upplýsingar um ${ssn} eru ekki tiltækar`);
      }
    }
  };

  const saveMultiChanges = async () => {
    const { ssn, allowMarketing, isVisibleInPhonebook, phoneNumber } = inputData;
    setLoading(true);
    if (subscriptionIds) {
      for (const subscriptionId of subscriptionIds) {
        if (ssn) {
          try {
            const { data } = await updateSubscription({
              variables: {
                input: {
                  contactSsn: ssn ?? null,
                  allowMarketing: allowMarketing,
                  isVisibleInPhonebook: isVisibleInPhonebook,
                  phoneNumber: isFiber ? phoneNumber : null,
                },
                subscriptionId,
              },
            });

            const {
              updateSubscription: { subscription, error },
            } = data;
            setLoading(false);

            if (error) {
              enqueueSnackbar(`${t('user.error')}: ${error.message}`, {
                variant: 'error',
              });
              return;
            }

            setProfile({
              name: subscription?.name,
              ssn: subscription?.ssn,
              allowMarketing: subscription?.allowMarketing,
              isVisibleInPhonebook: subscription?.isVisibleInPhonebook,
              phoneNumber: subscription?.phoneNumber,
              rateplan: subscription?.rateplan,
            });

            enqueueSnackbar(t('user.successfullyUpdated'), {
              variant: 'success',
            });
          } catch (e) {
            setLoading(false);

            enqueueSnackbar(`${t('user.error')}`, {
              variant: 'error',
            });
          }
        }
        router.push(`/${router?.query?.ssn}/fjoldaskraning`);
      }
    }
  };

  const saveChanges = async () => {
    const { ssn, allowMarketing, isVisibleInPhonebook, phoneNumber } = inputData;
    setLoading(true);

    try {
      const ssnChange = profile.ssn !== ssn;

      const { data } = await updateSubscription({
        variables: {
          input: {
            contactSsn: ssnChange ? ssn : null,
            allowMarketing: profile.allowMarketing !== allowMarketing ? allowMarketing : null,
            isVisibleInPhonebook:
              profile.isVisibleInPhonebook !== isVisibleInPhonebook ? isVisibleInPhonebook : null,
            phoneNumber:
              profile.phoneNumber !== phoneNumber || (ssnChange && isFiber) ? phoneNumber : null,
          },
          subscriptionId,
        },
      });

      const {
        updateSubscription: { subscription, error },
      } = data;
      setLoading(false);

      if (error) {
        enqueueSnackbar(`${t('user.error')}: ${error.message}`, {
          variant: 'error',
        });
        return;
      }

      setProfile({
        name: subscription?.name || profile.name,
        ssn: subscription?.ssn || profile.ssn,
        allowMarketing: subscription?.allowMarketing || profile.allowMarketing,
        isVisibleInPhonebook: subscription?.isVisibleInPhonebook || profile.isVisibleInPhonebook,
        phoneNumber: subscription?.phoneNumber || profile.phoneNumber,
        rateplan: subscription?.rateplan || profile.rateplan,
      });

      enqueueSnackbar(t('user.successfullyUpdated'), {
        variant: 'success',
      });
    } catch (e) {
      setLoading(false);

      enqueueSnackbar(`${t('user.error')}: ${e.message}`, {
        variant: 'error',
      });
    }
    setShowModal(false);
  };

  if (isRightHolderFlagActive && !isBundle && !isFiber && phonenumberRightHolderError) {
    enqueueSnackbar(t('user.errorRightHolder'), {
      variant: 'error',
    });
  }

  return (
    <Payment noContainer noSpacingTop>
      <PaymentSection
        title={
          !isRightHolderFlagActive
            ? t('user.userTitle')
            : isRightHolder
            ? t('user.userContactRightHolder')
            : t('user.userContact')
        }
        smallerTitle
        fullWidth
        noSpacingTop
      >
        <PaymentForm>
          <NumberTextBox
            name="kennitala"
            label={t('user.ssn')}
            defaultValue={profile.ssn}
            length={10}
            value={inputData.ssn}
            status={status}
            message={message}
            disabled={isBundle || !isStaff}
            onChange={(e: { target: { value: string } }) => onChangeSsn(e.target.value)}
          />
          <TextBox
            name="name"
            label={t('user.name')}
            defaultValue={profile.name}
            value={inputData.name}
            onChange={(e: { target: { value: string } }) => setNewValue(e.target.value, 'name')}
            disabled
          />
        </PaymentForm>
      </PaymentSection>
      {isRightHolderFlagActive && !isRightHolder && (
        <Box>
          <PaymentSection title={t('user.userRightHolder')} smallerTitle fullWidth noSpacingTop>
            <PaymentForm>
              <NumberTextBox
                name="kennitala"
                label={t('user.ssn')}
                defaultValue={rightHolderNationalId}
                length={10}
                value={rightHolderNationalId}
                disabled
              />
              <TextBox
                name="name"
                label={t('user.name')}
                defaultValue={rightHolderName}
                value={rightHolderName}
                disabled
              />
            </PaymentForm>
          </PaymentSection>
          {isStaff && (
            <Box marginBottom={10}>
              <Box marginBottom={2}>
                <Text variant="pSmallBold" color="warning">
                  {t('user.staffRightHolderChange')}
                </Text>
              </Box>
              <SecondaryButton
                text={t('user.staffRightHolderButtonChange')}
                onClick={() => changeRightHolder()}
                icon="checkMark"
              />
            </Box>
          )}
        </Box>
      )}
      {!isBundle && !isFiber && (
        <PaymentSection title={t('user.information.title')} smallerTitle fullWidth noSpacingTop>
          <Row>
            <Col col={6}>
              <CheckboxDeprecated
                color={subscriptionId ? color : 'pink'}
                name="isVisibleInPhonebook"
                checked={inputData.isVisibleInPhonebook}
                onChange={(e: { target: { checked: boolean } }) =>
                  setNewValue(e.target.checked, 'isVisibleInPhonebook')
                }
              >
                {t('user.information.isVisibleInPhonebook.title')}
                <small>{t('user.information.isVisibleInPhonebook.description')}</small>
              </CheckboxDeprecated>
            </Col>
            {inputData.isVisibleInPhonebook && (
              <Col col={6}>
                <CheckboxDeprecated
                  color={subscriptionId ? color : 'pink'}
                  name="allowMarketing"
                  checked={inputData.allowMarketing}
                  onChange={(e: { target: { checked: boolean } }) =>
                    setNewValue(e.target.checked, 'allowMarketing')
                  }
                >
                  {t('user.information.allowMarketing.title')}
                  <small>{t('user.information.allowMarketing.description')}</small>
                </CheckboxDeprecated>
              </Col>
            )}
          </Row>
        </PaymentSection>
      )}
      {isFiber && (
        <PaymentSection title={t('user.fiberInfo.contact')} smallerTitle fullWidth noSpacingTop>
          <NumberTextBox
            name="phoneNumber"
            label={t('user.fiberInfo.phoneNumber')}
            defaultValue={profile.phoneNumber}
            length={7}
            value={inputData.phoneNumber}
            disabled={isBundle}
            onChange={(e: { target: { value: string } }) =>
              setNewValue(e.target.value, 'phoneNumber')
            }
          />
        </PaymentSection>
      )}
      <PaymentSection fullWidth noSpacingTop>
        {!isBundle && (
          <Row>
            <Col col={5} orderMobile={2}>
              <Button
                onClick={() => cancelChanges()}
                background="white"
                text="dark"
                disabled={!isNewData || loading}
                big
              >
                {t('user.cancelChanges')}
              </Button>
            </Col>
            <Col col={6} push={1} orderMobile={1}>
              <Button
                background={subscriptionId ? color : 'pink'}
                disabled={!isNewData}
                loading={loading}
                big
                fill
                onClick={() => setShowModal(true)}
              >
                {t('user.saveChanges')}
              </Button>
            </Col>
          </Row>
        )}
        <Dialog
          ariaLabel={t('user.modalTitle')}
          onVisibilityChange={(isVisible: boolean) => setShowModal(isVisible)}
          isVisible={showModal}
          width={['11/12', '10/12', '6/12']}
        >
          <Box width="100%" display="flex" flexDirection="column">
            <ModalHeader title={t('user.modalTitle')} color={color} />
            <Box marginY={4} flexGrow={1}>
              {t('user.modalDescription')}
            </Box>
            {isRightHolderFlagActive && (
              <Box marginBottom={4}>
                <Text variant="pSmallBold" color="warning">
                  {t('user.dialogChangeInfo')}
                </Text>
              </Box>
            )}
            <Box display="flex" flexDirection={['column', 'row', 'row']} gap={4}>
              <MainButton
                text={t('user.modalBack')}
                colorScheme="white"
                onClick={() => setShowModal(false)}
                dottedShadow="none"
              />
              <MainButton
                text={t('user.modalConfirm')}
                colorScheme={color}
                icon="checkMark"
                onClick={subscriptionId ? saveChanges : saveMultiChanges}
                dottedShadow="none"
              />
            </Box>
          </Box>
        </Dialog>
      </PaymentSection>
    </Payment>
  );
};

const UserPage = ({ subscriptionId, subscriptionIds, ui, authentication, ...rest }: IPageProps) => {
  const { accountInput, isStaff } = authentication;

  const variables: { accountInput: typeof accountInput; subscriptionId?: typeof subscriptionId } = {
    accountInput,
  };

  if (subscriptionId) {
    variables.subscriptionId = subscriptionId;
  }

  const { loading, error, data } = useQuery<IUserData>(SUBSCRIPTIONUSER, {
    variables,
  });

  if ((loading || error || !data?.me?.profiles[0]) && subscriptionId) {
    return (
      <Settings subscriptionId={subscriptionId}>
        <div>Loading...</div>
      </Settings>
    );
  }

  if ((loading || error || !data?.me?.profiles[0]) && !subscriptionId) {
    return <div>Loading...</div>;
  }

  if (subscriptionId) {
    return (
      <Settings subscriptionId={subscriptionId}>
        <UserData
          profileData={data?.me?.profiles[0]}
          color={ui.pageColor}
          subscriptionId={subscriptionId}
          isStaff={isStaff}
          {...rest}
        />
      </Settings>
    );
  }

  if (subscriptionIds) {
    return (
      <UserData
        profileData={data?.me?.profiles[0]}
        color={ui.pageColor}
        subscriptionIds={subscriptionIds}
        isStaff={isStaff}
        {...rest}
      />
    );
  }
};

UserPage.getInitialProps = ({ query }: IPageProps) => {
  return {
    subscriptionId: query.subscriptionId ?? undefined,
    namespacesRequired: ['stillingar'],
  };
};

export default withTranslation('stillingar')(inject('ui', 'authentication')(UserPage));
