import React, { useState } from 'react';
import {
  Box,
  Icon,
  Input,
  MainButton,
  makeToast,
  SecondaryButton,
  Select,
  Text,
} from '@nova-hf/ui';
import Hradleid from 'beta/store/hradleid';
import { getMaxLengthOfName } from 'beta/utils/helpers';
import { useTranslation } from 'beta/utils/i18n';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';
import { IContext } from 'typings/context';
import {
  ContractFieldsToRemove,
  ContractItemType,
  useAddContractDepartmentMutation,
  useConnectDepartmentToContractMutation,
  useContractDepartmentsQuery,
  useRemoveFromContractMutation,
} from 'typings/graphql';

import MultiStepWrapper from '../../../containers/layout/MultiStepWrapper';

const COLOR = 'pink';

type DeildProps = {
  hradleid: Hradleid;
};

const Deild = ({ hradleid }: DeildProps) => {
  const { t } = useTranslation(['multi']);
  const router = useRouter();
  const customerId = router?.query?.customerId ?? '';
  const [checkedContracts, setCheckedContracts] = useState<string[]>();
  const [department, setDepartment] = useState('');
  const [newDepartment, setNewDepartment] = useState('');
  const [addOpen, setAddOpen] = useState(false);
  const { data, loading, error, refetch } = useContractDepartmentsQuery({
    variables: { input: { customerId: customerId.toString() } },
  });

  const departments = data?.contractDepartments?.departments;

  const mapContractsToUsernamesAndInfo = () => {
    return hradleid?.contracts?.map((contract) => {
      const serviceContractItem = contract?.contractItems.find(
        (item) => item.type === ContractItemType.Service,
      );
      const username = serviceContractItem
        ? serviceContractItem?.serviceInfo?.userName
        : t('multi:multi.noName');
      const departmentInfo = contract?.departmentName
        ? contract?.departmentName
        : t('multi:department.noDepartment');
      const MAX = getMaxLengthOfName();
      const truncatedName =
        username && username.length > MAX ? `${username.slice(0, MAX)}...` : username;

      return {
        name: truncatedName as string,
        info: departmentInfo,
        id: contract?.id,
        payer: contract?.paymentMethod?.customerId,
      };
    });
  };

  const [connectDepartment, { loading: loadingConnect }] = useConnectDepartmentToContractMutation(
    {},
  );

  const [removeDepartmentOnContract, { loading: loadingRemoveDepartmentOnContract }] =
    useRemoveFromContractMutation();

  const [addDepartment, { loading: loadingAdd }] = useAddContractDepartmentMutation({
    onCompleted: (data) => {
      makeToast.success(t('multi:department.addSuccess'), '');
      refetch();
      if (data?.addContractDepartment?.department?.id) {
        setDepartment(data?.addContractDepartment?.department?.id);
      }
    },
    onError: (error) => {
      makeToast.danger(t('multi:department.fail'), error.message);
    },
  });

  const onSubmit = async () => {
    try {
      const { data: connectToContractsData } = await connectDepartment({
        variables: {
          input: {
            contractIds: checkedContracts,
            departmentId: department,
          },
        },
      });
      if (!connectToContractsData) {
        makeToast.danger(t('multi:department.fail'), '');
      }
      if (connectToContractsData) {
        makeToast.success(t('multi:department.success'), '');
        router.push(`/beta/${customerId}/thjonustur`);
        hradleid?.incrementTrigger();
      }
    } catch (error) {
      if (error instanceof Error) makeToast.danger(t('multi:department.fail'), error.message);
    }
  };

  const onRemove = async () => {
    if (checkedContracts && checkedContracts.length) {
      try {
        for (const contractId of checkedContracts) {
          const { data: removeFromContractData } = await removeDepartmentOnContract({
            variables: {
              input: {
                id: contractId,
                fieldsToRemove: [ContractFieldsToRemove.DepartmentId],
              },
            },
          });

          if (!removeFromContractData) {
            makeToast.danger(t('multi:department.fail'), '');
          } else {
            makeToast.success(t('multi:department.success'), '');
          }
        }

        router.push(`/beta/${customerId}/thjonustur`);
        hradleid?.incrementTrigger();
      } catch (error) {
        if (error instanceof Error) makeToast.danger(t('multi:department.fail'), error.message);
      }
    }
  };

  const mappedContracts = mapContractsToUsernamesAndInfo();
  const contractsWhereCustomerIsNotPayer = mappedContracts?.filter(
    (contract) => contract.payer !== customerId,
  );
  const filteredContractIds = contractsWhereCustomerIsNotPayer?.map((contract) => contract.id);
  const getCheckedContracts = (contractIds: Array<string>) => {
    setCheckedContracts(contractIds);
  };

  const onAddClick = () => {
    setAddOpen(!addOpen);
  };

  const onEstablishClick = async () => {
    if (newDepartment.length < 1) {
      makeToast.danger(t('multi:department.addLengthFail'), '');
    } else {
      try {
        await addDepartment({
          variables: {
            input: {
              customerId: customerId.toString(),
              departmentName: newDepartment,
            },
          },
        });
      } catch (error) {
        if (error instanceof Error) {
          makeToast.danger(t('multi:department.fail'), error.message);
        }
      }
      setAddOpen(!addOpen);
    }
  };

  return (
    <MultiStepWrapper
      hradleid={hradleid}
      color={COLOR}
      disabledContracts={filteredContractIds ?? []}
      getMappedContracts={mappedContracts}
      sendCheckedToChild={getCheckedContracts}
      title={t('multi:department.title')}
      firstRowTitle={t('multi:headers.user')}
      secondRowTitle={t('multi:headers.department')}
      icon="transfer"
    >
      <Box display="flex" flexDirection="column" gap={10}>
        <Box>
          <Text color="black100" variant="h4">
            {t('multi:department.choose')}
          </Text>
          <Text color="black100">{t('multi:department.subtitle')}</Text>
        </Box>
        {!addOpen && (
          <Box>
            <Select
              id="title"
              label={t('multi:headers.department')}
              onChange={(e) => {
                setDepartment(e.target.value);
              }}
              isBold={false}
              disabled={false}
              value={department}
            >
              <option value="" disabled selected={department === ''}>
                {t('multi:department.placeholder')}
              </option>
              {departments?.map((dep) => {
                return (
                  <option key={dep.id} selected={dep.id === department} value={dep?.id ?? ''}>
                    {dep?.name}
                  </option>
                );
              })}
            </Select>
          </Box>
        )}
        <Box>
          <SecondaryButton
            onClick={() => onAddClick()}
            isDisabled={loadingAdd}
            icon={addOpen ? 'close' : 'add'}
            text={addOpen ? t('multi:department.close') : t('multi:department.add')}
            colorScheme="pink"
          ></SecondaryButton>
        </Box>
        {addOpen && (
          <>
            <Box marginTop={-10} width={{ sm: '100%', md: '6/12' }}>
              <Text color="black100">{t('multi:department.addInfo')}</Text>
            </Box>
            <Box
              marginTop={-10}
              width={{ sm: '100%', md: '6/12' }}
              display="flex"
              gap={2}
              flexDirection="column"
            >
              <Input
                label={t('multi:department.new')}
                id="department"
                name="department-name"
                onChange={(e) => setNewDepartment(e.target.value)}
                value={newDepartment}
                disabled={loadingAdd}
                isBold={false}
              />
              <MainButton
                onClick={() => onEstablishClick()}
                isDisabled={loadingAdd}
                icon="addCircle"
                text={t('multi:department.create')}
                colorScheme="pink"
              ></MainButton>
            </Box>
          </>
        )}
        {!addOpen && (
          <Box
            gap={3}
            display="flex"
            flexDirection="row"
            alignItems="center"
            marginTop={10}
            width="8/12"
            marginLeft="auto"
          >
            <MainButton
              colorScheme="warning"
              dottedShadow="none"
              text={'Fjarlægja deildir'}
              onClick={() => onRemove()}
              isDisabled={department !== '' || addOpen}
            />
            <MainButton
              colorScheme="pink"
              dottedShadow="none"
              text={t('multi:department.confirm')}
              onClick={() => onSubmit()}
              isDisabled={
                loading ||
                loadingConnect ||
                loadingRemoveDepartmentOnContract ||
                department === '' ||
                addOpen
              }
            />
          </Box>
        )}
        {error && (
          <Box alignItems="flex-end" display="flex" flexDirection="row" gap={1} marginTop={-10}>
            <Icon icon="info" color="warning" />
            <Text marginRight="auto" color="warning" variant="pSmallRegular">
              {t('multi:department.error')}
            </Text>
          </Box>
        )}
        {filteredContractIds && filteredContractIds.length > 0 && (
          <Box display="flex" flexDirection="row" alignItems="center" gap={1}>
            <Icon icon="info" color="warning" />
            <Text>{t('multi:department.payerError')}</Text>
          </Box>
        )}
      </Box>
    </MultiStepWrapper>
  );
};

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

export default inject('hradleid')(observer(Deild));
