import React, { useEffect, useState } from 'react';
import { NetworkStatus } from '@apollo/client';
import {
  Box,
  CardBase,
  Icon,
  ListBase,
  Menu as NavigationDropdown,
  NotificationBanner,
  Text,
} from '@nova-hf/ui';
import Konfetti from 'assets/svg/illustrations/konfetti.svg';
import ContractsHeader from 'beta/components/contracts-header/ContractsHeader';
import { ErrorBanner } from 'beta/components/error/ErrorBanner';
import SideMenuLayout from 'beta/components/layouts/SideMenuLayout';
import BundleContainer from 'beta/containers/bundle-container/BundleContainer';
import ContractList from 'beta/containers/contract-list/ContractList';
import Authentication from 'beta/store/authentication';
import Hradleid from 'beta/store/hradleid';
import { IContext } from 'beta/typings/context';
import { parseMainColor } from 'beta/utils/typeGuards';
import { uniq } from 'lodash';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';
import {
  Contract,
  useContractGroupsQuery,
  useContractsQuery,
  useCustomerNameQuery,
} from 'typings/graphql';
import { useTranslation } from 'utils/i18n';

const CONDENSED_PAGE_LIMIT = 10;
const PAGINATION_PAGE_LIMIT = 10;

const AllFilters = ['farsimi', 'netid', 'novatv', 'alltsaman', 'all', '4g/5gnet'] as const;
export type Filters = (typeof AllFilters)[number];

const isFilter = (value: string): value is Filters => {
  return AllFilters.includes(value as Filters);
};

type ThjonusturProps = {
  hradleid: Hradleid;
  authentication: Authentication;
};

const Thjonustur = ({ hradleid, authentication }: ThjonusturProps) => {
  const { t } = useTranslation(['services', 'errors']);
  const isStaff = authentication?.isStaff;
  const color = 'purple';
  const router = useRouter();
  const customerId: string = (router.query.customerId as string) ?? '';
  const [selectedFilter, setSelectedFilter] = useState<Filters>('all');
  const [checkedContractsCount, setCheckedContractsCount] = useState(0);
  const [selectedDepartment, setSelectedDepartment] = useState('');
  const [selectedVariant, setSelectedVariant] = useState('');
  const [closeWasPressed, setCloseWasPressed] = useState(false);
  const [pageLimit, setPageLimit] = useState(CONDENSED_PAGE_LIMIT);
  const [count, setCount] = useState(0);

  const { data: customerData } = useCustomerNameQuery({
    variables: {
      input: {
        id: (router.query.customerId as string) ?? '',
      },
    },
  });

  const isCompany = customerData?.customer?.isCompany;

  const { data, loading, error, networkStatus, refetch } = useContractGroupsQuery({
    variables: {
      input: {
        customerId,
      },
    },
    notifyOnNetworkStatusChange: true,
  });

  const { data: contractData } = useContractsQuery({
    variables: {
      input: {
        customerId,
      },
    },
  });

  const departments = contractData?.contracts?.contracts
    ?.map((contract) => contract?.departmentId)
    ?.filter((department) => department !== null && department !== undefined);

  const getDepartmentName = (departmentId: string) => {
    const department = contractData?.contracts?.contracts?.find(
      (contract) => contract?.departmentId === departmentId,
    );

    return department ? department.departmentName : '';
  };

  const uniqueDepartments = uniq(departments);

  const variants = contractData?.contracts?.contracts
    ?.map((contract) => contract?.variant?.id)
    ?.filter((variant) => variant !== null && variant !== undefined);

  const getVariantName = (variantId: string) => {
    const variant = contractData?.contracts?.contracts?.find(
      (contract) => contract?.variant?.id === variantId,
    );

    return variant ? variant?.variant?.name : '';
  };

  const uniqueVariants = uniq(variants);

  const handleSettingSelectedFilter = (filter: Filters) => {
    router.replace({
      query: { ...router.query, filterBy: filter.toLowerCase() },
    });
  };

  const handleSettingSelectedDepartment = (department: string) => {
    const query = department
      ? { ...router.query, department: department.toLowerCase() }
      : { ...router.query };
    router.replace({
      query,
    });
  };

  const handleSettingSelectedVariant = (variant: string) => {
    const query = variant
      ? { ...router.query, variant: variant.toLowerCase() }
      : { ...router.query };
    router.replace({
      query,
    });
  };

  const handleMenuSelection = (flow: string) => {
    router.push(`/beta/${customerId}/thjonustur/${flow}`);
  };

  useEffect(() => {
    if (router.query.filterBy) {
      setPageLimit(CONDENSED_PAGE_LIMIT);
      const queryString = router.query.filterBy as string;
      setSelectedFilter(queryString?.toLowerCase() as Filters);
    }
    if (router?.query?.department?.length) {
      const queryString = router.query.department as string;
      setSelectedDepartment(queryString?.toLowerCase());
    }
    if (router?.query?.variant?.length) {
      const queryString = router.query.variant as string;
      setSelectedVariant(queryString?.toLowerCase());
    }
  }, [router.query]);

  const allServices = selectedFilter === 'all';

  const onIconClick = () => {
    setCloseWasPressed(true);
  };

  let availableFilters = [
    {
      text: t('filterTitle.all'),
      category: 'all',
      onClick: () => {
        handleSettingSelectedFilter('all');
        setPageLimit(CONDENSED_PAGE_LIMIT);
      },
      isActive: selectedFilter === 'all',
      color: 'blue',
      count: 0,
    },
  ];
  const contractGroupsFilters = data?.contractGroups
    ?.filter((group) => !!group?.categoryId && group.categoryId === 'netid') // I tweaked this just to make sure only fiberContracts appear at the moment.
    .map((group) => {
      const categoryId = isFilter((group?.categoryId?.toLowerCase() as string) ?? '')
        ? (group?.categoryId?.toLowerCase() as Filters)
        : 'all';
      return {
        text: group?.categoryName ?? '',
        category: group?.categoryId?.toLowerCase() ?? '',
        onClick: () => {
          handleSettingSelectedFilter(categoryId);
          setPageLimit(PAGINATION_PAGE_LIMIT);
        },
        isActive: selectedFilter === categoryId,
        color: parseMainColor(group?.brandColor ?? '', 'pink') ?? 'pink',
        count: group?.contractCount ?? 0,
      };
    });

  availableFilters =
    contractGroupsFilters !== undefined
      ? [...availableFilters, ...contractGroupsFilters]
      : availableFilters;

  const displayCategories = availableFilters.filter((c) =>
    selectedFilter === 'all' ? c.category !== 'all' : c.category === selectedFilter,
  );

  const allDepartments = {
    text: t('departmentFilterTitle'),
    departmentId: '',
    onClick: () => {
      const { department, ...remainingQuery } = router.query; // eslint-disable-line no-unused-vars
      router.replace({
        query: remainingQuery,
      });
      setPageLimit(PAGINATION_PAGE_LIMIT);
      setSelectedDepartment('');
    },
    isActive: selectedDepartment === '',
    color: color,
  };
  const departmentFilters = [
    ...uniqueDepartments.map((department) => ({
      text: getDepartmentName(department ?? ''),
      departmentId: department,
      onClick: () => {
        handleSettingSelectedDepartment(department ?? '');
        setPageLimit(PAGINATION_PAGE_LIMIT);
      },
      isActive: department === selectedDepartment,
      color: color,
    })),
    allDepartments,
  ];

  const allVariants = {
    text: t('variantFilterTitle'),
    variantId: '',
    onClick: () => {
      const { variant, ...remainingQuery } = router.query; // eslint-disable-line no-unused-vars
      router.replace({
        query: remainingQuery,
      });
      setPageLimit(PAGINATION_PAGE_LIMIT);
      setSelectedVariant('');
    },
    isActive: selectedVariant === '',
    color: color,
  };

  const variantFilters = [
    ...uniqueVariants.map((variant) => ({
      text: getVariantName(variant ?? ''),
      variantId: variant,
      onClick: () => {
        handleSettingSelectedVariant(variant ?? '');
        setPageLimit(PAGINATION_PAGE_LIMIT);
      },
      isActive: variant === selectedVariant,
      color: color,
    })),
    allVariants,
  ];

  const getCheckedContracts = (contracts: Contract[]) => {
    if (closeWasPressed) {
      setCloseWasPressed(false);
    }
    setCheckedContractsCount(contracts?.length);
    hradleid.setContracts(contracts);
  };

  const getCount = (count: number) => {
    setCount(count);
  };

  return (
    <SideMenuLayout
      color="purple"
      title={t('temporaryTitle')}
      hasMultiSelectBanner={checkedContractsCount > 0 && !closeWasPressed}
      multiSelectBannerProps={{
        isOnBottom: true,
        icon: 'close',
        iconClick: () => {
          onIconClick();
        },
        color: color,
        text: t('multiSelect.chosen'),
        isInverted: false,
        count: checkedContractsCount,
        tooltip: {
          children: (
            <CardBase borderColor="grey200" dottedShadow="none" hasBorder>
              <Box padding={2}>
                <Text marginBottom={1} variant="pSmallBold">
                  {t('multiSelect.tooltipTitle')}
                </Text>
                <Text marginBottom={1} variant="pXSmallRegular">
                  {t('multiSelect.tooltipInfo')}
                </Text>
              </Box>
            </CardBase>
          ),
          placement: 'bottom-end',
          shouldShowOnHover: true,
          color: color,
        },
        menuItems: [
          {
            onClick: () => {
              handleMenuSelection('greidslumati');
            },
            text: t('multiMethods.paymentMethod'),
          },
          isStaff
            ? {
                onClick: () => {
                  handleMenuSelection('thjonustuleidabreyting');
                },
                text: t('multiMethods.pack'),
              }
            : null,
          isStaff
            ? {
                onClick: () => {
                  handleMenuSelection('greidandi');
                },
                text: t('multiMethods.payer'),
              }
            : null,
          isCompany
            ? {
                onClick: () => {
                  handleMenuSelection('deild');
                },
                text: t('multiMethods.department'),
              }
            : null,
          isCompany
            ? {
                onClick: () => {
                  handleMenuSelection('thak');
                },
                text: t('multiMethods.roof'),
              }
            : null,
        ].filter(Boolean),
      }}
      heroChildren={
        <Box display="flex" justifyContent="flex-end" gap={1} marginY={[3, 0]}>
          {contractGroupsFilters && contractGroupsFilters?.length > 0 && (
            <NavigationDropdown
              color="purple"
              disclosure={
                <Box
                  display="inline-flex"
                  alignItems="center"
                  gap={1}
                  renderAs="button"
                  boxShadow={{ focusVisible: 'focused' }}
                >
                  <Text variant="pMediumBold">{t(`filterTitle.${selectedFilter}`)}</Text>
                  <Icon icon="arrowDown" color="purple" />
                </Box>
              }
              items={availableFilters}
              label="select"
            />
          )}
          {uniqueDepartments && uniqueDepartments?.length > 0 && (
            <NavigationDropdown
              color="purple"
              disclosure={
                <Box
                  display="inline-flex"
                  alignItems="center"
                  gap={1}
                  renderAs="button"
                  boxShadow={{ focusVisible: 'focused' }}
                >
                  <Text variant="pMediumBold">
                    {selectedDepartment && selectedDepartment.length
                      ? getDepartmentName(selectedDepartment)
                      : t('departmentFilterTitle')}
                  </Text>
                  <Icon icon="arrowDown" color="purple" />
                </Box>
              }
              items={departmentFilters}
              label="select"
            />
          )}
          {uniqueVariants && uniqueVariants?.length > 0 && (
            <NavigationDropdown
              color="purple"
              disclosure={
                <Box
                  display="inline-flex"
                  alignItems="center"
                  gap={1}
                  renderAs="button"
                  boxShadow={{ focusVisible: 'focused' }}
                >
                  <Text variant="pMediumBold">
                    {selectedVariant && selectedVariant.length
                      ? getVariantName(selectedVariant)
                      : t('variantFilterTitle')}
                  </Text>
                  <Icon icon="arrowDown" color="purple" />
                </Box>
              }
              items={variantFilters}
              label="select"
            />
          )}
        </Box>
      }
    >
      {(loading || error) && (
        <>
          {loading && <ContractsHeader title={t('loadingTitle')} />}
          <ErrorBanner
            eyebrowTexts={[
              t('errors:thjonustur.eyebrows.1'),
              t('errors:thjonustur.eyebrows.2'),
              t('errors:thjonustur.eyebrows.3'),
            ]}
            titles={[
              t('errors:thjonustur.titles.1'),
              t('errors:thjonustur.titles.2'),
              t('errors:thjonustur.titles.3'),
            ]}
            descriptions={[
              t('errors:thjonustur.descriptions.1'),
              t('errors:thjonustur.descriptions.2'),
              t('errors:thjonustur.descriptions.3'),
            ]}
            icon="zap"
            color="attention"
            showLoading={loading || networkStatus === NetworkStatus.refetch}
            refetchButton={{
              text: t('errors:buttons.refresh'),
              icon: 'refresh',
              onClick: () => refetch(),
            }}
            loadingComponent={
              <>
                <ListBase isLoading gap={3} />
                <ListBase isLoading gap={3} />
                <ListBase isLoading />
              </>
            }
          />
        </>
      )}
      {!error && !loading && (!data?.contractGroups || !data.contractGroups.length) && (
        <Box>
          <NotificationBanner
            eyebrowText={t('notCustomer.eyebrow')}
            title={t('notCustomer.title')}
            description={t('notCustomer.description')}
            icon="novaLogo"
            mainButtonColored={{
              text: t('notCustomer.becomeACustomerButton'),
              icon: 'heart',
              renderAs: 'a',
              href: 'https://www.nova.is/farsimi/komdu/1',
              openInNewTab: true,
            }}
            mainButtonWhite={{
              text: t('notCustomer.whyNovaButton'),
              icon: 'longArrowRight',
              renderAs: 'a',
              href: 'https://www.nova.is/dansgolfid/thess-vegna-nova',
              openInNewTab: true,
            }}
          />
          <Box marginTop={-30} display="flex" width="100%">
            <Konfetti />
          </Box>
        </Box>
      )}
      {!!data?.contractGroups?.length && (
        <Box display="flex" flexDirection="column">
          {displayCategories
            .filter((c) => c.category)
            .sort((a, b) => {
              const aContainsNumber = /\d/.test(a.category);
              const bContainsNumber = /\d/.test(b.category);
              return aContainsNumber === bContainsNumber
                ? a.category.localeCompare(b.category)
                : bContainsNumber
                ? -1
                : 1;
            })
            .map((c) => {
              if (c.category === 'alltsaman') {
                return <BundleContainer key={c.category} title={c.text} category={c.category} />;
              }
              return (
                <>
                  <ContractList
                    key={c.category}
                    title={c.text}
                    isShowingAllServices={allServices}
                    getChosenService={c.onClick}
                    perPageLimit={pageLimit}
                    category={c.category as Filters}
                    color={parseMainColor(c.color, 'ocean')}
                    contractCount={count}
                    getCount={getCount}
                    departmentId={selectedDepartment}
                    variantId={selectedVariant}
                    getCheckedContracts={getCheckedContracts}
                    uncheckContracts={closeWasPressed}
                  />
                </>
              );
            })}
        </Box>
      )}
    </SideMenuLayout>
  );
};

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

export default inject('hradleid', 'authentication')(observer(Thjonustur));
