import { Fragment, forwardRef, useState } from 'react';
import { useInfiniteQuery } from 'react-query';

import { AxiosResponse } from 'axios';
import { useDebounce } from '@material-hu/hooks/useDebounce';
import Box from '@material-hu/mui/Box';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuChips from '@material-hu/components/design-system/Chip';
import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import HuTable from '@material-hu/components/design-system/Table';
import HuTableBody from '@material-hu/components/design-system/Table/components/TableBody';
import HuTableCell from '@material-hu/components/design-system/Table/components/TableCell';
import HuTableContainer from '@material-hu/components/design-system/Table/components/TableContainer';
import HuTableHead from '@material-hu/components/design-system/Table/components/TableHead';
import HuTableRow from '@material-hu/components/design-system/Table/components/TableRow';

import EllipsisTooltip from 'src/components/EllipsisTooltip';

import { useAuth } from 'src/contexts/JWTContext';
import useGeneralError from 'src/hooks/useGeneralError';
import { Visibility } from 'src/types/instance';
import { InsightsAudienceResponse, InsightsTypes } from 'src/types/posts';
import { formatUTCLocalDate } from 'src/utils/date';
import { getFullName } from 'src/utils/userUtils';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { isVisible } from 'src/utils/instance';
import { getListItemsLength, getNextPage } from 'src/utils/pagination';

import InfiniteList from 'src/components/list/InfiniteList';
import { UserNameLink } from 'src/components/UserNameLink';

import InsightsAudienceSkeleton from './InsightsAudienceSkeleton';
import InsightsCardContainer from './InsightsCardContainer';

const LIMIT = 25;
const ROW_HEIGHT = 64;

type Header = {
  id: string;
  text: string;
  enabled: boolean;
};

export type InsightsAudienceProps = {
  serviceProps: {
    service: (
      type: InsightsTypes,
      page?: number,
      limit?: number,
      query?: string,
    ) => Promise<AxiosResponse<InsightsAudienceResponse, any>>;
    key: (type: InsightsTypes, query: string) => (string | number)[];
  };
  downloadProps: {
    isDownloading: boolean;
    onDownload: () => void;
  };
};

const InsightsAudience = forwardRef<typeof Box, InsightsAudienceProps>(
  function InsightsAudienceComponent(props, ref) {
    const { serviceProps, downloadProps } = props;

    const [type, setType] = useState<InsightsTypes>(InsightsTypes.VIEWERS);
    const [query, setQuery] = useState<string>('');

    const { t } = useTranslation('post');
    const { user: loggedUser, instance, permissions } = useAuth();
    const showGeneralError = useGeneralError();
    const debouncedQuery = useDebounce(query);

    const { service, key } = serviceProps;
    const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
      useInfiniteQuery(
        key(type, debouncedQuery),
        ({ pageParam = 1 }) => service(type, pageParam, LIMIT, debouncedQuery),
        {
          getNextPageParam: (_, pages) =>
            getNextPage(getListItemsLength(pages), LIMIT, pages),
          onError: err => {
            showGeneralError(err, t('error_loading_insights_audience'));
          },
        },
      );

    const count = data?.pages[0]?.data?.count || 0;
    const isEmpty = !data || count === 0;

    const handleChangeType = (newType: InsightsTypes) => {
      setType(newType);
    };

    const handleChangeQuery = (value: string) => setQuery(value);

    const isEmailVisible = isVisible(
      instance?.emailInProfileVisibility || Visibility.USER_AND_ADMINS,
      loggedUser!,
      permissions,
    );

    const isViewerType = type === InsightsTypes.VIEWERS;

    const headers: Header[] = [
      { id: 'fullName', text: t('general:full_name'), enabled: true },
      { id: 'user', text: t('user'), enabled: true },
      { id: 'email', text: t('email'), enabled: isEmailVisible },
      {
        id: isViewerType ? 'viewDate' : 'lastUpdate',
        text: t(isViewerType ? 'view_date' : 'last_update'),
        enabled: true,
      },
    ].filter(header => header.enabled);

    const { onDownload, isDownloading } = downloadProps;

    return (
      <InsightsCardContainer
        title={t('post:audience_web')}
        onDownload={onDownload}
        isDownloadingReport={isDownloading}
        ref={ref}
      >
        <Box
          sx={{
            borderRadius: '8px',
            height: `${9 * ROW_HEIGHT}px`,
          }}
        >
          <HuSearch
            value={query}
            onChange={handleChangeQuery}
            placeholder={t('search_users')}
            aria-label={t('search_users')}
            fullWidth
            sx={{ mb: 3 }}
          />
          <Stack sx={{ mb: 4, flexDirection: 'row', gap: 1 }}>
            {Object.values(InsightsTypes).map(insightType => (
              <HuChips
                key={insightType}
                label={t(insightType)}
                isSelected={type === insightType}
                onClick={() => handleChangeType(insightType)}
              />
            ))}
          </Stack>
          {!debouncedQuery && isEmpty && (
            <>
              {isLoading && <InsightsAudienceSkeleton />}
              {!isLoading && (
                <Typography
                  color="textSecondary"
                  variant="subtitle2"
                  sx={{
                    textAlign: 'center',
                    mt: 2,
                  }}
                >
                  {t('post:no_results_web')}
                </Typography>
              )}
            </>
          )}
          {(debouncedQuery || !isEmpty) && (
            <>
              {!isLoading && (
                <Stack sx={{ mb: 1 }}>
                  <Typography
                    variant="globalS"
                    fontWeight="fontWeightSemiBold"
                  >
                    {t(`total_${type.toLowerCase()}`, { count })}
                  </Typography>
                </Stack>
              )}
              <InfiniteList
                isSuccess={!!data}
                isEmpty={isEmpty}
                isLoading={isLoading}
                renderSkeleton={<InsightsAudienceSkeleton />}
                loadingSkeleton={isLoading}
                fetchNextPage={fetchNextPage}
                hasNextPage={hasNextPage}
                isFetchingNextPage={isFetchingNextPage}
                noResultsLabel={t('no_results_search')}
                sx={{
                  height: `calc(100% - ${3 * ROW_HEIGHT}px)`,
                  overflow: 'scroll',
                }}
              >
                <HuTableContainer>
                  <HuTable>
                    <HuTableHead>
                      <HuTableRow headerRow>
                        {headers.map(header => (
                          <HuTableCell
                            headerCell
                            key={header.id}
                            sx={{ px: 2 }}
                          >
                            {header.text}
                          </HuTableCell>
                        ))}
                      </HuTableRow>
                    </HuTableHead>
                    <HuTableBody>
                      {data?.pages?.map((page, index) => (
                        <Fragment key={index}>
                          {page.data?.items?.map(user => (
                            <HuTableRow key={user.id}>
                              <HuTableCell
                                sx={{
                                  display: 'flex',
                                  flexDirection: 'row',
                                  alignItems: 'center',
                                  maxWidth: '290px',
                                  minWidth: 0,
                                  overflow: 'hidden',
                                  borderBottom: 'none',
                                  px: 2,
                                }}
                              >
                                <EllipsisTooltip title={getFullName(user)}>
                                  <Box
                                    component="span"
                                    sx={{
                                      display: 'flex',
                                      alignItems: 'center',
                                      minWidth: 0,
                                      overflow: 'hidden',
                                      maxWidth: '290px',
                                    }}
                                  >
                                    <UserNameLink
                                      user={user}
                                      showProfilePicture
                                      truncate
                                      sx={{ fontWeight: 400 }}
                                    />
                                  </Box>
                                </EllipsisTooltip>
                              </HuTableCell>
                              <HuTableCell
                                sx={{
                                  whiteSpace: 'nowrap',
                                  maxWidth: '180px',
                                  px: 2,
                                }}
                              >
                                <EllipsisTooltip
                                  title={user.employeeInternalId ?? ''}
                                >
                                  <Typography
                                    noWrap
                                    sx={{ maxWidth: '180px' }}
                                  >
                                    {user.employeeInternalId}
                                  </Typography>
                                </EllipsisTooltip>
                              </HuTableCell>
                              {isEmailVisible && (
                                <HuTableCell
                                  sx={{
                                    whiteSpace: 'nowrap',
                                    maxWidth: '200px',
                                    px: 2,
                                  }}
                                >
                                  <EllipsisTooltip title={user.email || '-'}>
                                    <Typography
                                      noWrap
                                      sx={{ maxWidth: '200px' }}
                                    >
                                      {user.email || '-'}
                                    </Typography>
                                  </EllipsisTooltip>
                                </HuTableCell>
                              )}
                              <HuTableCell
                                sx={{
                                  textTransform: 'capitalize',
                                  px: 2,
                                  minWidth: '180px',
                                }}
                              >
                                <Typography noWrap>
                                  {formatUTCLocalDate(
                                    user.firstInteraction ||
                                      user.lastInteraction,
                                    loggedUser!,
                                    ' MMM d y',
                                  )}
                                </Typography>
                              </HuTableCell>
                            </HuTableRow>
                          ))}
                        </Fragment>
                      ))}
                    </HuTableBody>
                  </HuTable>
                </HuTableContainer>
              </InfiniteList>
            </>
          )}
        </Box>
      </InsightsCardContainer>
    );
  },
);

export default InsightsAudience;
