import React, { useEffect, useState } from 'react';
import { NetworkStatus } from '@apollo/client';
import {
  Box,
  CardBase,
  Checkbox,
  Grid,
  GridItem,
  Hyphen,
  Icon,
  ListBase,
  Pill,
  Separator,
  Text,
  Tooltip,
  useViewport,
} from '@nova-hf/ui';
import { MainColorType } from '@nova-hf/ui/umd/ts/src/styles/vars.css';
import ContractsHeader from 'beta/components/contracts-header/ContractsHeader';
import { ErrorBanner } from 'beta/components/error/ErrorBanner';
import PaginationContainer from 'beta/components/layouts/Pagination';
import { Filters } from 'beta/pages/thjonustur';
import Authentication from 'beta/store/authentication';
import Hradleid from 'beta/store/hradleid';
import UI from 'beta/store/ui';
import {
  contractStatusColorIconMap,
  deviceMap,
  serviceColorMap,
  serviceIconMap,
} from 'beta/utils/helpers';
import { uniqBy } from 'lodash';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';
import { TFunction } from 'next-i18next';
import {
  Contract,
  ContractStatus,
  DeviceContractItem,
  PlanType,
  ServiceContractItem,
  ServiceType,
  SlimService,
  useContractListQuery,
} from 'typings/graphql';
import { useTranslation } from 'utils/i18n';

import ContractExtraInfo from './contractExtraInfo';

const errorMessages = (category: Filters, t: TFunction) => {
  switch (category) {
    case '4g/5gnet':
      return {
        eyebrowTexts: [
          t('errors:contractList.4g/5gnet.eyebrows.1'),
          t('errors:contractList.4g/5gnet.eyebrows.2'),
          t('errors:contractList.4g/5gnet.eyebrows.3'),
        ],
        titles: [
          t('errors:contractList.4g/5gnet.titles.1'),
          t('errors:contractList.4g/5gnet.titles.2'),
          t('errors:contractList.4g/5gnet.titles.3'),
        ],
        descriptions: [
          t('errors:contractList.4g/5gnet.descriptions.1'),
          t('errors:contractList.4g/5gnet.descriptions.2'),
          t('errors:contractList.4g/5gnet.descriptions.3'),
        ],
      };
    case 'alltsaman':
      return {
        eyebrowTexts: [
          t('errors:contractList.alltsaman.eyebrows.1'),
          t('errors:contractList.alltsaman.eyebrows.2'),
          t('errors:contractList.alltsaman.eyebrows.3'),
        ],
        titles: [
          t('errors:contractList.alltsaman.titles.1'),
          t('errors:contractList.alltsaman.titles.2'),
          t('errors:contractList.alltsaman.titles.3'),
        ],
        descriptions: [
          t('errors:contractList.alltsaman.descriptions.1'),
          t('errors:contractList.alltsaman.descriptions.2'),
          t('errors:contractList.alltsaman.descriptions.3'),
        ],
      };
    case 'novatv':
      return {
        eyebrowTexts: [
          t('errors:contractList.novatv.eyebrows.1'),
          t('errors:contractList.novatv.eyebrows.2'),
          t('errors:contractList.novatv.eyebrows.3'),
        ],
        titles: [
          t('errors:contractList.novatv.titles.1'),
          t('errors:contractList.novatv.titles.2'),
          t('errors:contractList.novatv.titles.3'),
        ],
        descriptions: [
          t('errors:contractList.novatv.descriptions.1'),
          t('errors:contractList.novatv.descriptions.2'),
          t('errors:contractList.novatv.descriptions.3'),
        ],
      };
    case 'netid':
      return {
        eyebrowTexts: [
          t('errors:contractList.netid.eyebrows.1'),
          t('errors:contractList.netid.eyebrows.2'),
          t('errors:contractList.netid.eyebrows.3'),
        ],
        titles: [
          t('errors:contractList.netid.titles.1'),
          t('errors:contractList.netid.titles.2'),
          t('errors:contractList.netid.titles.3'),
        ],
        descriptions: [
          t('errors:contractList.netid.descriptions.1'),
          t('errors:contractList.netid.descriptions.2'),
          t('errors:contractList.netid.descriptions.3'),
        ],
      };
    case 'farsimi':
      return {
        eyebrowTexts: [
          t('errors:contractList.farsimi.eyebrows.1'),
          t('errors:contractList.farsimi.eyebrows.2'),
          t('errors:contractList.farsimi.eyebrows.3'),
        ],
        titles: [
          t('errors:contractList.farsimi.titles.1'),
          t('errors:contractList.farsimi.titles.2'),
          t('errors:contractList.farsimi.titles.3'),
        ],
        descriptions: [
          t('errors:contractList.farsimi.descriptions.1'),
          t('errors:contractList.farsimi.descriptions.2'),
          t('errors:contractList.farsimi.descriptions.3'),
        ],
      };
    default:
      return {
        eyebrowTexts: [
          t('errors:contractList.default.eyebrows.1'),
          t('errors:contractList.default.eyebrows.2'),
          t('errors:contractList.default.eyebrows.3'),
        ],
        titles: [
          t('errors:contractList.default.titles.1'),
          t('errors:contractList.default.titles.2'),
          t('errors:contractList.default.titles.3'),
        ],
        descriptions: [
          t('errors:contractList.default.descriptions.1'),
          t('errors:contractList.default.descriptions.2'),
          t('errors:contractList.default.descriptions.3'),
        ],
      };
  }
};

export const tooltipMessage = (
  t: TFunction,
): Record<ContractStatus, { title: string; description: string }> => ({
  Active: {
    title: t('status.serviceStatus.Active.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Pending: {
    title: t('status.serviceStatus.Pending.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Restricted: {
    title: t('status.serviceStatus.Restricted.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Cancelled: {
    title: t('status.serviceStatus.Cancelled.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Canceled: {
    title: t('status.serviceStatus.Canceled.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Abandoned: {
    title: t('status.serviceStatus.Abandoned.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Trialing: {
    title: t('status.serviceStatus.Trialing.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Unpaid: {
    title: t('status.serviceStatus.Unpaid.title'),
    description: t('status.serviceStatus.Active.description'),
  },
  Unknown: {
    title: t('status.serviceStatus.Unknown.title'),
    description: t('status.serviceStatus.Active.description'),
  },
});

type ContractListProps = {
  getChosenService: () => void;
  getCount: (count: number) => void;
  getCheckedContracts: (contracts: Contract[]) => void;
  isShowingAllServices: boolean;
  perPageLimit: number;
  title: string;
  category: Filters;
  departmentId: string;
  variantId: string;
  color: MainColorType;
  contractCount?: number;
  authentication: Authentication;
  ui: UI;
  hradleid: Hradleid;
  uncheckContracts: boolean;
};

const ContractList = ({
  getCheckedContracts,
  getCount,
  perPageLimit,
  category,
  departmentId,
  variantId,
  title,
  color,
  contractCount,
  authentication,
  ui,
  hradleid,
  uncheckContracts,
}: ContractListProps) => {
  const { t } = useTranslation(['services', 'errors']);
  const router = useRouter();
  const customerId = router.query.customerId as string;
  const isStaff = authentication?.isStaff;
  const { isXLarge } = useViewport();
  const [page, setPage] = useState(1);
  const [perPage, setPerPage] = useState(perPageLimit);
  const [checkedContracts, setCheckedContracts] = useState<Contract[]>([]);
  const handleCheckboxClick = (contract: Contract) => {
    if (ui.showContactBubble) {
      ui.setShowContactBubble(false);
    }
    if (checkedContracts.includes(contract)) {
      setCheckedContracts(checkedContracts.filter((item) => item.id !== contract.id));
    } else {
      setCheckedContracts([...checkedContracts, contract]);
    }
  };
  const handleBoxClick = (id: string, isService: boolean) => {
    if (isService) {
      authentication.isComingFromBeta = true;
      router.push(`/beta/${customerId}/thjonustur/${id}`);
    }
    if (!isService) {
      authentication.isComingFromBeta = true;
      router.push(`/beta/${customerId}/askriftir/${id}`);
    }
  };

  useEffect(() => {
    setPage(1);
  }, [variantId, departmentId]);

  const { data, loading, error, refetch, networkStatus } = useContractListQuery({
    variables: {
      input: {
        customerId,
        page,
        per_page: perPage,
        category:
          router?.query?.filterBy && router?.query?.filterBy !== 'all'
            ? router.query.filterBy.toString()
            : undefined,
        departmentId,
        variantId,
        planType: PlanType.Postpaid,
      },
    },
    notifyOnNetworkStatusChange: true,
  });

  const contracts = data?.contractsWithPagination?.contracts;
  const totalContracts = data?.contractsWithPagination?.pageInfo?.totalCount;
  const isCondensed = !!(
    totalContracts &&
    contractCount &&
    perPage < totalContracts &&
    (contractCount >= perPage || page !== 1)
  );

  const contractsWithServices = contracts?.filter((contract) => {
    return contract.contractItems.some(
      (contractItem) => contractItem.__typename === 'ServiceContractItem',
    );
  });

  const uniqContractsWithServices = uniqBy(contractsWithServices, 'id');

  const addressSplit = (address: string) => {
    return address.split(',');
  };

  const handleChooseAll = () => {
    if (ui.showContactBubble) {
      ui.setShowContactBubble(false);
    }
    const allAreChecked = uniqContractsWithServices.length === checkedContracts.length;
    if (uniqContractsWithServices && !allAreChecked) {
      setCheckedContracts(uniqContractsWithServices);
    } else {
      setCheckedContracts([]);
    }
  };

  const buttonClick = () => {
    setPerPage(totalContracts ?? perPageLimit);
  };

  useEffect(() => {
    getCount(contracts?.length ?? 0);
  }, [contracts]);

  useEffect(() => {
    getCheckedContracts(checkedContracts);
  }, [checkedContracts]);

  useEffect(() => {
    setCheckedContracts([]);
  }, [uncheckContracts]);

  useEffect(() => {
    setPerPage(perPageLimit);
  }, [perPageLimit]);

  useEffect(() => {
    refetch();
  }, [hradleid.trigger]);

  const extractSpeedFromName = (text: string) => {
    const speedRegex = /\s(\d+(\.\d+)?)\sGb\/s$/;
    const commonPart = text.replace(speedRegex, '');
    return commonPart.trim();
  };

  if (loading || error || !contracts) {
    const messages = errorMessages(category, t);
    return (
      <Box marginBottom={5}>
        <ContractsHeader title={title} />
        <ErrorBanner
          eyebrowTexts={messages.eyebrowTexts}
          titles={messages.titles}
          descriptions={messages.descriptions}
          icon="zap"
          color={color}
          showLoading={loading || networkStatus === NetworkStatus.refetch}
          refetchButton={{
            text: t('errors:buttons.refresh'),
            icon: 'refresh',
            onClick: () => refetch(),
          }}
          loadingComponent={
            <>
              {[...Array(contractCount && contractCount > 0 ? contractCount : 2)].map((_x, i) => (
                <ListBase key={i} isLoading gap={3} />
              ))}
            </>
          }
        />
      </Box>
    );
  }

  if (!contracts?.length) {
    return (
      <Box>
        <Text>{t('services:noServices')}</Text>
      </Box>
    );
  }

  return (
    <Box marginBottom={5}>
      <ContractsHeader
        color={color}
        pillText={contractCount?.toString() ?? '0'}
        title={title}
        button={{
          text: t('services.addService'),
          icon: 'add',
          wrapper: (link) => (
            <a
              href={'https://www.nova.is/netid/ljosleidari'}
              target="_blank"
              rel="noopener noreferrer"
            >
              {link}
            </a>
          ),
        }}
      />
      {isXLarge ? (
        <Box paddingLeft={5} paddingY={3} marginBottom={2} backgroundColor="white">
          <Grid gridTemplate={{ xl: 12 }} alignItems="center" rowGap={{ xl: 3 }}>
            <GridItem gridColumn={{ xl: 'span3' }}>
              <Box alignItems="center" display="flex" flexDirection="row" gap={8}>
                <Box display="flex" gap={1} flexDirection="column" alignItems="center">
                  <Checkbox
                    isChecked={checkedContracts.length === uniqContractsWithServices.length}
                    type="checked"
                    color={color}
                    onChange={() => {
                      handleChooseAll();
                    }}
                  />
                  <Text variant="pXSmallBold">{t('services:multiSelect.selectAll')}</Text>
                </Box>
                <Text variant="eyebrowMedium">{t('services:multiSelect.user')}</Text>
              </Box>
            </GridItem>
            <GridItem gridColumn={{ xl: 'span2' }}>
              <Text variant="eyebrowMedium">{t('services:multiSelect.info')}</Text>
            </GridItem>
            <GridItem gridColumn={{ xl: 'span2' }}>
              <Text marginLeft={-3} variant="eyebrowMedium">
                {t('services:multiSelect.service')}
              </Text>
            </GridItem>
            <GridItem gridColumn={{ xl: 'span3' }}>
              <Text marginLeft={-3} variant="eyebrowMedium">
                {t('services:multiSelect.cost')}
              </Text>
            </GridItem>
            <GridItem gridColumn={{ xl: 'span2' }}>
              <Text marginLeft={-3} variant="eyebrowMedium">
                {t('services:multiSelect.paymentMethod')}
              </Text>
            </GridItem>
          </Grid>
        </Box>
      ) : (
        <Box marginBottom={2} padding={2} backgroundColor="white">
          <Box display="flex" gap={1} flexDirection="row" alignItems="center">
            <Checkbox
              isChecked={checkedContracts.length === uniqContractsWithServices.length}
              type="checked"
              color={color}
              onChange={() => {
                handleChooseAll();
              }}
            />
            <Text variant="pSmallBold">{t('services:multiSelect.selectAll')}</Text>
          </Box>
        </Box>
      )}
      {contracts.map((contract) => {
        const contractItems = contract.contractItems.filter(
          (contractItem) => contractItem.__typename === 'ServiceContractItem',
        );
        const deviceContractItems = contract.contractItems.filter(
          (contractItem) => contractItem.__typename === 'DeviceContractItem',
        );

        const hasActiveDevice = (deviceContractItems as DeviceContractItem[])?.find(
          (contractItem) => contractItem.status === 'Active',
        );

        const hasActiveRouter = (deviceContractItems as DeviceContractItem[])?.find(
          (contractItem) =>
            contractItem.variant?.id?.includes('router') && contractItem.status === 'Active',
        );

        const service: SlimService | undefined =
          (contractItems as ServiceContractItem[])?.find(
            (contractItem) => contractItem.serviceInfo?.type === ServiceType.Fiber,
          )?.serviceInfo ?? undefined;

        const contractStatus: ContractStatus = contract?.status ?? ContractStatus.Unknown;
        const serviceLayout = contractStatusColorIconMap(contractStatus);

        const isDisabled = contract?.status !== ContractStatus.Active;
        const isPending = contract?.status === ContractStatus.Pending;

        const pillText =
          contract.variant?.__typename === 'SubscriptionVariant' ||
          contract.variant?.__typename === 'ProvisionedSubscriptionVariant'
            ? contract.variant.planType === PlanType.Postpaid
              ? t('services.postpaid')
              : contract.variant.planType === PlanType.Prepaid
              ? t('services.prepaid')
              : ''
            : '';
        return (
          <Box key={contract.id} marginBottom={2}>
            <ListBase
              renderAs="a"
              onClick={() => handleBoxClick(service?.id ?? contract?.id, !!service)}
              backgroundColor={isDisabled && !isPending && !hasActiveDevice ? 'grey200' : 'white'}
              gap={3}
            >
              <Grid gridTemplate={{ sm: 6, lg: 12 }} alignItems="center" rowGap={{ sm: 3 }}>
                <GridItem gridColumn={{ sm: 'span6', xl: 'span4' }}>
                  <Box display="flex" flexDirection="row" alignItems="center" gap={1}>
                    <Box
                      padding={3}
                      onClick={(event) => {
                        event.stopPropagation();
                      }}
                    >
                      <Checkbox
                        isChecked={checkedContracts.includes(contract as Contract)}
                        type="checked"
                        color={color}
                        isDisabled={isDisabled && !isPending}
                        onChange={() => {
                          handleCheckboxClick(contract as Contract);
                        }}
                      />
                    </Box>
                    <Box>
                      <Box
                        style={{
                          whiteSpace: 'nowrap',
                          overflow: 'hidden',
                          textOverflow: 'ellipsis',
                        }}
                        gap={2}
                        alignItems="center"
                        display="flex"
                        flexDirection="row"
                        marginLeft={-2}
                      >
                        <Icon
                          size={48}
                          icon={
                            service?.type
                              ? serviceIconMap(service?.type)
                              : deviceMap(hasActiveDevice && hasActiveRouter ? 'router' : 'kastari')
                          }
                          color={service?.type ? serviceColorMap(service?.type) : 'purple'}
                        />
                        <Box>
                          <Text variant="pMediumBold">{service?.userName?.split(' ')[0]}</Text>
                          <Box renderAs="span" display="flex" alignItems="center">
                            <Text renderAs="span" variant="pXSmallRegular" color="grey600">
                              {t('services.paidBy')}&nbsp;
                              <Box renderAs="span" color="black100">
                                {contract?.payerName?.split(' ')[0]}
                              </Box>
                            </Text>
                          </Box>
                          {contract?.departmentName && (
                            <Box marginRight={5} renderAs="span" display="flex" alignItems="center">
                              <Text renderAs="span" variant="pXSmallRegular" color="grey600">
                                {t('services.department')}&nbsp;
                                <Box renderAs="span" color="black100">
                                  {contract?.departmentName}
                                </Box>
                              </Text>
                            </Box>
                          )}
                        </Box>
                      </Box>
                    </Box>
                  </Box>
                </GridItem>
                <GridItem gridColumn={{ sm: 'span6' }} hiddenOn={['lg', 'xl']}>
                  <Separator negativeSpace={3} />
                </GridItem>
                <GridItem gridColumn={{ sm: 'span6', xl: 'span2' }}>
                  {service ? (
                    <Box display="flex" flexDirection="row" alignItems="center" gap={2}>
                      <Tooltip
                        color={serviceLayout.color}
                        icon={serviceLayout.icon}
                        placement="top-start"
                        size={16}
                      >
                        <CardBase dottedShadow="none" borderColor="grey200" hasBorder>
                          <Box display="flex" gap={1} padding={2}>
                            <Text variant="pMediumBold" noWrap>
                              {tooltipMessage(t)[contractStatus].title}
                            </Text>
                            <Text variant="pXSmallRegular">
                              {tooltipMessage(t)[contractStatus].description}
                            </Text>
                          </Box>
                        </CardBase>
                      </Tooltip>
                      <Box>
                        <Text variant="pMediumBold">
                          <Hyphen>{addressSplit(service?.nickname ?? '')[0]}</Hyphen>
                        </Text>
                        <Text variant="pXSmallRegular">
                          {addressSplit(service?.nickname ?? '')[1]}
                        </Text>
                      </Box>
                    </Box>
                  ) : (
                    <Box display="flex" flexDirection="row" alignItems="center" gap={2}>
                      <Tooltip
                        color={hasActiveDevice ? 'success' : 'warning'}
                        icon={hasActiveDevice ? 'checkMark' : 'close'}
                        placement="top-start"
                        size={16}
                      >
                        <CardBase dottedShadow="none" borderColor="grey200" hasBorder>
                          <Box display="flex" gap={1} padding={2}>
                            <Text variant="pMediumBold" noWrap>
                              {hasActiveDevice
                                ? t('services:activeDeviceTooltipTitle')
                                : t('services:noActiveDeviceTooltipTitle')}
                            </Text>
                          </Box>
                        </CardBase>
                      </Tooltip>
                      <Box>
                        <Text variant="pMediumBold">
                          {isStaff
                            ? hasActiveDevice?.rentalInfo?.trackingCode
                            : hasActiveRouter
                            ? t('services:router')
                            : t('services:device')}
                        </Text>
                        <Text variant="pXSmallRegular">{contract?.variant?.name}</Text>
                      </Box>
                    </Box>
                  )}
                </GridItem>
                <GridItem gridColumn={{ sm: 'span6', lg: 'span12' }} hiddenOn={['xl']}>
                  <Separator negativeSpace={3} />
                </GridItem>
                <GridItem gridColumn={{ sm: 'span4', xl: 'span2' }}>
                  <Text variant="pMediumBold">
                    <Hyphen>
                      {extractSpeedFromName(
                        contract?.variant?.name && !!service ? contract?.variant?.name : 'Áskrift',
                      )}
                    </Hyphen>
                  </Text>
                  <ContractExtraInfo contractId={contract?.id} color={color} info="usage" />
                </GridItem>
                <GridItem gridColumn={{ sm: 'span4', xl: 'span2' }}>
                  <ContractExtraInfo contractId={contract?.id} color={color} info="charge" />
                </GridItem>
                <GridItem gridColumn={{ sm: 'span6', lg: 'span3', xl: 'span2' }}>
                  <Box
                    display="flex"
                    justifyContent={{ sm: 'space-between', lg: 'flex-end' }}
                    gap={[5, 2, 5]}
                  >
                    <Pill
                      text={pillText}
                      color={isDisabled && !isPending && !hasActiveDevice ? 'white' : 'grey200'}
                      maxWidth="7/12"
                    />
                    <Icon icon="longArrowRight" color="grey400" />
                  </Box>
                </GridItem>
              </Grid>
            </ListBase>
          </Box>
        );
      })}
      <PaginationContainer
        buttonText={t('services:services.seeAll', { total: totalContracts })}
        color={color}
        page={page}
        perPage={perPage}
        onSelectPage={setPage}
        total={totalContracts ?? 0}
        onButtonClick={buttonClick}
        isCondensedView={isCondensed}
      />
    </Box>
  );
};

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