import { useCallback } from 'react';
import {
  type FetchNextPageOptions,
  type InfiniteQueryObserverResult,
} from 'react-query';
import { useNavigate } from 'react-router-dom';

import { type AxiosResponse } from 'axios';
import { type HuTableSortingHeaderProps } from '@material-hu/hooks/TableSorting/useHuServerTableSorting';
import { type SxProps } from '@material-hu/mui/styles';

import Pills, {
  type PillsProps,
} from '@material-hu/components/design-system/Pills';
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 TableHead from '@material-hu/components/design-system/Table/components/TableHead';
import TableLoader from '@material-hu/components/design-system/Table/components/TableLoader';
import TableRow from '@material-hu/components/design-system/Table/components/TableRow';
import Title from '@material-hu/components/design-system/Title';

import { IconSearch } from '@material-hu/icons/tabler';

import { recruitingRoutes } from 'src/pages/dashboard/Recruiting/routes';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { CandidatesTableEmptyState } from '../../../../components/CandidatesTableEmptyState';
import { TableError } from '../../../../components/TableError';
import { TableNoInternetConnection } from '../../../../components/TableNoInternetConnection';
import { TableSkeleton } from '../../../../components/TableSkeleton';
import {
  type CandidateResponse,
  type HiredCandidateResponse,
  type HiringPipelineWithCountResponse,
  JobOfferStatus,
  type PaginatedResponse,
  type RejectedCandidateResponse,
} from '../../../../types';

type ColumnContent = {
  key: string;
  text: string;
  description?: string;
  type: 'text' | 'pills';
  pillType?: PillsProps['type'];
  sx?: SxProps;
  withEllipsis?: boolean;
};

export type JobOfferCandidatesTableProps = {
  totalCount: number;
  isLoading: boolean;
  isFetchingNextPage: boolean;
  hasNextPage: boolean;
  fetchNextPage: (
    options?: FetchNextPageOptions,
  ) => Promise<
    InfiniteQueryObserverResult<
      AxiosResponse<
        PaginatedResponse<
          CandidateResponse | HiredCandidateResponse | RejectedCandidateResponse
        >,
        unknown
      >,
      unknown
    >
  >;
  onScrollToTop: () => void;
  noInternetConnection: boolean;
  errorCount: number;
  refetch: () => void;
  HuTableSortingHeader: React.ComponentType<HuTableSortingHeaderProps>;
  jobId?: number | null;
  selectedStage: HiringPipelineWithCountResponse | null;
  tableConfig: {
    columns: {
      type: 'cell' | 'sortingCell';
      label: string;
      id?: string;
      sx?: SxProps;
    }[];
    rows: {
      id: number;
      columns: ColumnContent[];
    }[];
    type: 'active' | 'hired' | 'rejected' | 'closed';
  };
  jobStatus?: JobOfferStatus;
  isSearchActive?: boolean;
};

export const JobOfferCandidatesTable = ({
  jobStatus,
  HuTableSortingHeader,
  totalCount,
  isLoading,
  isFetchingNextPage,
  fetchNextPage,
  onScrollToTop,
  noInternetConnection,
  errorCount,
  refetch,
  jobId,
  selectedStage,
  tableConfig,
  isSearchActive = false,
}: JobOfferCandidatesTableProps) => {
  const { t } = useLokaliseTranslation(['ats', 'material_hu_only', 'general']);
  const navigate = useNavigate();
  const onRowClick = (id: number) => {
    navigate(recruitingRoutes.JobApplicationDetail(jobId, id));
  };
  const { rows } = tableConfig;

  const getTextCellContent = (textCell: ColumnContent) => {
    return (
      <Title
        title={textCell.text}
        {...(textCell.description && { description: textCell.description })}
        {...(textCell.withEllipsis && {
          withEllipsis: true,
          overflow: 'tooltip',
        })}
        fontWeight="fontWeightRegular"
        variant="S"
      />
    );
  };

  const getEmptyStateConfig = useCallback(() => {
    const activeConfig = {
      title: '',
      description: '',
    };
    const closedConfig = {
      title: t('job_candidates.list.closed.title'),
      description: t('job_candidates.list.closed.description'),
    };
    const isOpenJob = jobStatus === JobOfferStatus.OPEN;
    switch (tableConfig.type) {
      case 'active':
        if (jobStatus === JobOfferStatus.CLOSED) {
          return closedConfig;
        }
        return activeConfig;
      case 'rejected':
        return {
          title: t('job_candidates.list.empty_state.rejected.title'),
          description: isOpenJob
            ? ''
            : t('job_candidates.list.empty_state.rejected.description'),
          isStageFilter: isOpenJob,
        };
      case 'hired':
        return {
          title: t('job_candidates.list.empty_state.hired.title'),
          description: isOpenJob
            ? ''
            : t('job_candidates.list.empty_state.hired.description'),
          isStageFilter: isOpenJob,
        };
      case 'closed':
        return closedConfig;
      default:
        return activeConfig;
    }
  }, [jobStatus, t, tableConfig.type]);

  if (noInternetConnection) {
    return <TableNoInternetConnection onRetry={refetch} />;
  }

  if (rows.length === 0 && !isLoading && !errorCount) {
    if (isSearchActive) {
      return (
        <CandidatesTableEmptyState
          icon={IconSearch}
          title={t('general:no_results_for_search')}
        />
      );
    }
    return (
      <CandidatesTableEmptyState
        isStageFilter={!!selectedStage}
        {...getEmptyStateConfig()}
      />
    );
  }

  if (errorCount > 0) {
    return (
      <TableError
        errorCount={errorCount}
        onRetry={refetch}
      />
    );
  }

  return (
    <>
      <TableContainer
        sx={{
          mb: 2,
          maxWidth: 1040,
          mx: 'auto',
          boxSizing: 'border-box',
          overflowX: { xs: 'auto', md: 'hidden' },
        }}
      >
        <Table
          sx={{
            borderCollapse: 'collapse',
            '& th, & td': {
              border: 0,
            },
          }}
        >
          <TableHead>
            <TableRow
              headerRow
              sx={{ height: 74, boxSizing: 'border-box' }}
            >
              {tableConfig.columns.map((column, index) =>
                column.type === 'cell' ? (
                  <TableCell
                    key={column.label}
                    headerCell
                    sx={{
                      boxSizing: 'border-box',
                      width: index === 0 ? 224 : 204,
                      minWidth: index === 0 ? 224 : 204,
                      p: 2,
                      ...column.sx,
                    }}
                  >
                    {column.label}
                  </TableCell>
                ) : (
                  <HuTableSortingHeader
                    key={column.label}
                    id={column.id ?? ''}
                    sx={{
                      boxSizing: 'border-box',
                      width: index === 0 ? 224 : 204,
                      minWidth: index === 0 ? 224 : 204,
                      p: 2,
                      ...column.sx,
                    }}
                  >
                    {column.label}
                  </HuTableSortingHeader>
                ),
              )}
            </TableRow>
          </TableHead>
          <TableBody>
            {isLoading && (
              <TableSkeleton
                rows={5}
                cols={tableConfig.columns.length}
              />
            )}
            {!isLoading &&
              rows.map(row => {
                const { columns, id } = row;
                return (
                  <TableRow
                    key={id}
                    onClick={() => onRowClick(id)}
                    sx={{ cursor: 'pointer', height: 74 }}
                  >
                    {columns.map(column => (
                      <TableCell
                        key={column.key}
                        sx={{ p: 2, ...column.sx }}
                      >
                        {column.type === 'text' ? (
                          getTextCellContent(column)
                        ) : (
                          <Pills
                            label={column.text}
                            type={column.pillType ?? 'neutral'}
                            hasIcon={false}
                            size="small"
                            sx={column.sx}
                          />
                        )}
                      </TableCell>
                    ))}
                  </TableRow>
                );
              })}
            {isFetchingNextPage && (
              <TableSkeleton
                rows={3}
                cols={tableConfig.columns.length}
              />
            )}
          </TableBody>
        </Table>
      </TableContainer>
      {!isLoading && (
        <TableLoader
          loadedCount={rows.length}
          totalCount={totalCount}
          onLoadMore={fetchNextPage}
          onScrollToTop={onScrollToTop}
          slotProps={{
            button: {
              disabled: isFetchingNextPage,
            },
          }}
        />
      )}
    </>
  );
};
