import { useCallback, useState } from 'react';

import TableSkeleton from '@material-hu/components/composed-components/TableSkeleton';
import { useSnackbar } from '@material-hu/components/design-system/Snackbar';
import Table from '@material-hu/components/design-system/Table';
import TableBody from '@material-hu/components/design-system/Table/components/TableBody';
import TableCell from '@material-hu/components/design-system/Table/components/TableCell';
import TableContainer from '@material-hu/components/design-system/Table/components/TableContainer';
import TableLoader from '@material-hu/components/design-system/Table/components/TableLoader';
import TableRowComponent from '@material-hu/components/design-system/Table/components/TableRow';

import { PaginatedQueryStates } from 'src/hooks/usePaginatedQueryState';
import { SessionStatus } from 'src/pages/dashboard/Learning/Sessions/constants';
import { useGetSessionAttendance } from 'src/pages/dashboard/Learning/Sessions/hooks/useGetSessionAttendance';
import { type SessionDetail } from 'src/pages/dashboard/Learning/Sessions/types';
import { addOrRemoveSet } from 'src/utils/arrayUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { handleScrollToTop } from 'src/utils/tableUtils';

import { TableHeader } from './TableHeader';
import { TableRow } from './TableRow';
import { TableSearch } from './TableSearch';
import { TableStates } from './TableStates';
import { TableToolbar } from './TableToolbar';

type AttendanceTableProps = {
  session?: SessionDetail;
};

export const AttendanceTable = ({ session }: AttendanceTableProps) => {
  const { enqueueSnackbar } = useSnackbar();
  const { t } = useLokaliseTranslation(['learning', 'material_hu_only']);
  const [selectedCollaborators, setSelectedCollaborators] = useState(
    new Set<number>(),
  );

  const {
    handleFetchNextPage,
    refetch,
    collaborators,
    queryState,
    isFetching,
    totalCount,
    isFetchingNextPage,
  } = useGetSessionAttendance(session?.id);

  const isAllSelected =
    selectedCollaborators.size === collaborators.length && queryState.isSuccess;

  const handleResetSelection = () => setSelectedCollaborators(new Set());

  const handleSelectCollaborators = useCallback(
    (userId?: number) => {
      if (session?.status !== SessionStatus.finished) {
        enqueueSnackbar({
          title: t('session.attendance.not_available'),
          description: t('session.attendance.not_available_description'),
          variant: 'info',
        });
        return;
      }

      let newSelection: Set<number>;

      if (userId) {
        newSelection = addOrRemoveSet(selectedCollaborators, userId);
      } else {
        if (isAllSelected) newSelection = new Set();
        else newSelection = new Set(collaborators.map(c => c.userId));
      }

      setSelectedCollaborators(newSelection);
    },
    [session, t, selectedCollaborators, collaborators],
  );

  const isLoading =
    queryState.isLoading || queryState.state === PaginatedQueryStates.IDLE;

  const skeletonCols =
    !session?.id || session?.status !== SessionStatus.finished ? 4 : 5;
  const showTable = collaborators.length > 0 || isFetchingNextPage || isLoading;

  return (
    <>
      <TableSearch />
      <TableStates
        queryState={queryState}
        onRetry={refetch}
      />
      {showTable && (
        <TableContainer>
          <TableToolbar
            selectedCollaborators={selectedCollaborators}
            onResetSelection={handleResetSelection}
            sessionId={session?.id}
          />
          <Table
            stickyHeader
            id="attendance-table"
            sx={{
              opacity: isFetching ? 0.5 : 1,
              transition: isFetching ? 'opacity 0.2s ease-in-out' : 'none',
              pointerEvents: isFetching ? 'none' : 'auto',
            }}
          >
            {collaborators.length > 0 && (
              <TableHeader
                onSelectAllCollaborators={handleSelectCollaborators}
                sessionStatus={session?.status}
                checked={isAllSelected}
                selectedCollaborators={selectedCollaborators}
              />
            )}
            <TableBody
              sx={{
                ...((isFetchingNextPage || isLoading) && {
                  '& tr td:first-of-type': {
                    width: 68,
                    borderRight: ({ palette }) =>
                      `1px solid ${palette.border?.neutralBorder}`,
                  },
                }),
              }}
            >
              {isLoading && (
                <TableSkeleton
                  cols={skeletonCols}
                  rows={4}
                />
              )}
              {collaborators.map(collaborator => (
                <TableRow
                  key={collaborator.id}
                  collaborator={collaborator}
                  sessionStatus={session?.status}
                  sessionId={session?.id}
                  onSelectCollaborator={handleSelectCollaborators}
                  checked={selectedCollaborators.has(collaborator.userId)}
                />
              ))}
              {isFetchingNextPage && (
                <TableSkeleton
                  cols={skeletonCols}
                  rows={4}
                />
              )}
              {collaborators.length > 0 && (
                <TableRowComponent>
                  <TableCell
                    sx={{
                      p: 0,
                      '& .MuiStack-root': {
                        borderRadius: 0,
                      },
                    }}
                    colSpan={12}
                  >
                    <TableLoader
                      loadedCount={collaborators.length}
                      totalCount={totalCount}
                      onLoadMore={handleFetchNextPage}
                      onScrollToTop={() =>
                        handleScrollToTop('attendance-table')
                      }
                    />
                  </TableCell>
                </TableRowComponent>
              )}
            </TableBody>
          </Table>
        </TableContainer>
      )}
    </>
  );
};
