import { useMemo, useState } from 'react';
import { Helmet } from 'react-helmet-async';
import { useInfiniteQuery } from 'react-query';
import { useNavigate } from 'react-router-dom';

import { upperFirst } from 'lodash-es';
import { IconCircleCheck } from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import TableSkeleton from '@material-hu/components/composed-components/TableSkeleton';
import HuAvatar from '@material-hu/components/design-system/Avatar';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuTaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import Pills, {
  type PillsProps,
} from '@material-hu/components/design-system/Pills';
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 HuTabs from '@material-hu/components/design-system/Tabs';

import { useDebounce } from 'src/hooks/useDebounce';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { groupRoutes } from 'src/pages/dashboard/Groups/routes';
import {
  getCompanyInvitations,
  getReceivedCompanyInvitations,
} from 'src/services/groupsService';
import {
  type CompanyInvitation,
  type CompanyInvitationStatus,
} from 'src/types/groups';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { flatPages } from 'src/utils/tableUtils';
import { formatUTCDate } from 'src/utils/timeUtils';
import { shouldThrowError } from 'src/utils/typeUtils';

import { InfiniteList } from 'src/components/InfiniteList';
import EmptyTableState from 'src/components/Table/EmptyTableState/EmptyTableState';
import { NoMoreResultsFooter } from 'src/components/Table/EmptyTableState/NoMoreResultsFooter';

const LIMIT = 20;

const statusToPillType = (
  status: CompanyInvitationStatus,
): PillsProps['type'] => {
  switch (status) {
    case 'APPROVED':
      return 'success';
    case 'REJECTED':
      return 'error';
    case 'EXPIRED':
      return 'warning';
    case 'PENDING':
      return 'info';
    case 'ACCEPTED':
      return 'success';
    default:
      shouldThrowError(status);
  }
};

const SENT_HEADER_IDS = [
  'headers.group_name',
  'headers.invitation_owner',
  'headers.request_date',
  'headers.resolution_owner',
  'headers.status',
];

const RECEIVED_HEADER_IDS = [
  'headers.group_name',
  'headers.inviting_community',
  'headers.inviting_user',
  'headers.privacy',
  'headers.status',
];

const GroupInvitationsTableHeader = ({
  headerIds,
  t,
}: {
  headerIds: string[];
  t: (key: string) => string;
}) => (
  <HuTableHead>
    <HuTableRow headerRow>
      {headerIds.map(id => (
        <HuTableCell
          key={id}
          headerCell
        >
          <Typography
            variant="globalS"
            fontWeight="fontWeightSemiBold"
          >
            {t(`group:multicompany_invitations.${id}`)}
          </Typography>
        </HuTableCell>
      ))}
    </HuTableRow>
  </HuTableHead>
);

enum TabKey {
  SENT = 'sent',
  RECEIVED = 'received',
}

const MultiCompanyInvitationsEmptyState = ({ label }: { label: string }) => {
  return (
    <Box
      sx={{
        backgroundColor: theme =>
          theme.palette.hugoBackground?.neutralBgTerciary,
        border: theme =>
          `1px solid ${
            theme.palette.new?.border?.neutral?.default ??
            theme.palette.border?.neutralDivider
          }`,
        borderRadius: theme => theme.shape.borderRadiusL,
        overflow: 'hidden',
        width: '100%',
      }}
    >
      <Box
        sx={{
          display: 'flex',
          justifyContent: 'center',
          py: 3,
        }}
      >
        <Stack
          sx={{
            alignItems: 'center',
            justifyContent: 'center',
            gap: 2,
          }}
        >
          <HuAvatar
            size="large"
            Icon={IconCircleCheck}
          />
          <Typography
            variant="globalS"
            fontWeight="fontWeightRegular"
          >
            {label}
          </Typography>
        </Stack>
      </Box>
    </Box>
  );
};

const GroupsCompanyInvitationsPage = () => {
  const { t } = useLokaliseTranslation(['general', 'group']);
  const navigate = useNavigate();
  const HuGoThemeProvider = useHuGoTheme();

  const [activeTab, setActiveTab] = useState<TabKey>(TabKey.SENT);
  const [query, setQuery] = useState('');
  const { debouncedValue, setImmediately: setImmediatelyDebouncedQuery } =
    useDebounce(query);

  const handleTabChange = (value: string) => {
    if (value === activeTab) return;
    setActiveTab(value as TabKey);
    setQuery('');
    setImmediatelyDebouncedQuery('');
  };

  const tabs = useMemo(
    () => [
      {
        label: t('group:multicompany_invitations.tabs.sent'),
        value: TabKey.SENT,
      },
      {
        label: t('group:multicompany_invitations.tabs.received'),
        value: TabKey.RECEIVED,
      },
    ],
    [t],
  );

  const sentQuery = useInfiniteQuery(
    ['groups', 'company-invitations', TabKey.SENT, debouncedValue],
    ({ pageParam = '' }) =>
      getCompanyInvitations({
        limit: LIMIT,
        cursor: pageParam || undefined,
        q: debouncedValue || null,
      }),
    {
      enabled: activeTab === TabKey.SENT,
      getNextPageParam: lastPage => lastPage?.data?.cursor,
    },
  );

  const receivedQuery = useInfiniteQuery(
    ['groups', 'company-invitations', TabKey.RECEIVED, debouncedValue],
    ({ pageParam = '' }) =>
      getReceivedCompanyInvitations({
        limit: LIMIT,
        cursor: pageParam || undefined,
        q: debouncedValue || null,
      }),
    {
      enabled: activeTab === TabKey.RECEIVED,
      getNextPageParam: lastPage => lastPage?.data?.cursor,
    },
  );

  const currentQuery = activeTab === TabKey.SENT ? sentQuery : receivedQuery;

  const invitations = flatPages<CompanyInvitation>(currentQuery.data);
  const isLoading = currentQuery.isLoading;
  const isFetchingNextPage = currentQuery.isFetchingNextPage;
  const hasNextPage = !!currentQuery.hasNextPage;
  const isEmpty =
    !isLoading && !currentQuery.isError && invitations.length === 0;
  const showEmptyState = isEmpty && !debouncedValue;
  const showNoResultsState = isEmpty && !!debouncedValue;

  const showNoMoreResultsFooter =
    !isLoading &&
    !currentQuery.isError &&
    invitations.length > 0 &&
    !hasNextPage;

  const title = t('group:multicompany_invitations.title');
  const headerIds =
    activeTab === TabKey.SENT ? SENT_HEADER_IDS : RECEIVED_HEADER_IDS;

  return (
    <>
      <Helmet>
        <title>{formatTitle(title)}</title>
      </Helmet>

      <HuGoThemeProvider>
        <Stack
          sx={{
            backgroundColor: theme => theme.palette.hugoBackground?.neutralBg,
            minHeight: '100%',
          }}
        >
          <HuTaskFocusHeader
            title={title}
            onBack={() => navigate(groupRoutes.base())}
            onClose={() => navigate(groupRoutes.base())}
          />

          <Stack
            sx={{
              px: { xs: 4, md: 12 },
              py: 4,
              gap: 2,
              flex: 1,
              width: '100%',
              mx: 'auto',
            }}
          >
            <Box>
              <HuTabs
                value={activeTab}
                onTabChange={handleTabChange}
                tabs={tabs}
                defaultValue={TabKey.SENT}
              />
            </Box>

            {showEmptyState && (
              <MultiCompanyInvitationsEmptyState
                label={t('group:multicompany_invitations.empty')}
              />
            )}

            {!showEmptyState && (
              <HuCardContainer
                fullWidth
                sx={{
                  '& .MuiCardContent-root': {
                    display: 'flex',
                    flexDirection: 'column',
                    gap: 2,
                  },
                }}
              >
                <Box
                  sx={{
                    borderRadius: theme => theme.shape.borderRadiusL,
                    backgroundColor: theme =>
                      theme.palette.hugoBackground?.neutralBg,
                    padding: 2,
                  }}
                >
                  <HuSearch
                    value={query}
                    onChange={setQuery}
                    fullWidth
                    placeholder={t('general:search')}
                  />
                </Box>
                <InfiniteList
                  sx={{ p: 0 }}
                  // Added isLoading to allow table's loading fallback to be rendered.
                  isSuccess={!!currentQuery.data || isLoading}
                  isLoading={isLoading}
                  // We render skeleton rows inside the table (not the default centered spinner).
                  loadingFallback={<></>}
                  isEmpty={false}
                  fetchNextPage={currentQuery.fetchNextPage}
                  hasNextPage={currentQuery.hasNextPage}
                  isFetchingNextPage={isFetchingNextPage}
                  // We render skeleton rows inside the table.
                  renderSkeleton={<></>}
                >
                  <HuTableContainer sx={{ width: '100%', overflow: 'auto' }}>
                    <HuTable>
                      <GroupInvitationsTableHeader
                        headerIds={headerIds}
                        t={t}
                      />
                      <HuTableBody>
                        {!isLoading &&
                          invitations.map(invitation => (
                            <HuTableRow key={invitation.id}>
                              {activeTab === TabKey.SENT ? (
                                <>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography variant="globalS">
                                      {invitation.group?.title ?? '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography
                                      variant="globalS"
                                      noWrap
                                    >
                                      {invitation.createdByName || '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography
                                      variant="globalS"
                                      noWrap
                                    >
                                      {invitation.createdAt
                                        ? formatUTCDate(invitation.createdAt)
                                        : '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography
                                      variant="globalS"
                                      noWrap
                                    >
                                      {invitation.invitedEmail || '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell>
                                    <Pills
                                      type={statusToPillType(invitation.status)}
                                      hasIcon={false}
                                      label={upperFirst(
                                        invitation.status.toLowerCase(),
                                      )}
                                      // variant="filled"
                                      size="small"
                                    />
                                  </HuTableCell>
                                </>
                              ) : (
                                <>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography variant="globalS">
                                      {invitation.group?.title ?? '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography
                                      variant="globalS"
                                      noWrap
                                    >
                                      {invitation.instanceName || '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography
                                      variant="globalS"
                                      noWrap
                                    >
                                      {invitation.createdByName || '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell sx={{ whiteSpace: 'nowrap' }}>
                                    <Typography
                                      variant="globalS"
                                      noWrap
                                    >
                                      {invitation.group?.privacyPolicy
                                        ? t(
                                            `group:${invitation.group.privacyPolicy.toLowerCase()}`,
                                          )
                                        : '-'}
                                    </Typography>
                                  </HuTableCell>
                                  <HuTableCell>
                                    <Pills
                                      type={statusToPillType(invitation.status)}
                                      hasIcon={false}
                                      label={upperFirst(
                                        invitation.status.toLowerCase(),
                                      )}
                                      size="small"
                                    />
                                  </HuTableCell>
                                </>
                              )}
                            </HuTableRow>
                          ))}

                        {showNoResultsState && (
                          <EmptyTableState
                            totalColumns={headerIds.length}
                            titleProps={{
                              title: t('general:no_results'),
                            }}
                          />
                        )}
                        {(isLoading || isFetchingNextPage) && (
                          <TableSkeleton
                            rows={3}
                            cols={headerIds.length}
                          />
                        )}
                      </HuTableBody>
                    </HuTable>
                  </HuTableContainer>
                </InfiniteList>

                {showNoMoreResultsFooter && (
                  <Stack sx={{ mt: 1 }}>
                    <NoMoreResultsFooter />
                  </Stack>
                )}
              </HuCardContainer>
            )}
          </Stack>
        </Stack>
      </HuGoThemeProvider>
    </>
  );
};

export default GroupsCompanyInvitationsPage;
