import { useMemo, useRef, useState } from 'react';

import TableFilterDecorator from '@composed-components/peopleExperience/TableFilterDecorator';
import CardContainer from '@design-system/CardContainer';
import { Menu } from '@design-system/Menu';
import { MenuItem } from '@design-system/Menu/components/MenuItem';
import Table from '@design-system/Table';
import TableBody from '@design-system/Table/components/TableBody';
import TableCell from '@design-system/Table/components/TableCell';
import TableContainer from '@design-system/Table/components/TableContainer';
import TableHead from '@design-system/Table/components/TableHead';
import TableLoader from '@design-system/Table/components/TableLoader';
import TableRow from '@design-system/Table/components/TableRow';
import Title from '@design-system/Title';
import {
  Button,
  cardContentClasses,
  Fade,
  Stack,
  Typography,
  useTheme,
} from '@mui/material';
import { IconChevronDown } from '@tabler/icons-react';
import { times } from 'lodash';

import CommentListRowSkeleton from './components/CommentListRowSkeleton';
import {
  defaultColumnHeadings,
  defaultFilterLabels,
  filterOptions,
  INITIAL_SKELETON_ROWS,
  LOADING_MORE_SKELETON_ROWS,
} from './constants';
import {
  type CommentData,
  type CommentsTableListProps,
  FilterOption,
} from './types';
import { getFilterColors } from './utils';

type Column = {
  id: string;
  heading: string;
  width: string;
  renderCell: (row: CommentData) => React.ReactNode;
};

const CommentsTableList = ({
  title = 'Comments',
  columnHeadings = defaultColumnHeadings,
  filterLabels = defaultFilterLabels,
  selectedFilter = FilterOption.ALL,
  onFilterChange,
  data = [],
  loading = false,
  loadingMore = false,
  isPreviousData = false,
  loadedCount = 0,
  totalCount = 0,
  onLoadMore,
  onScrollToTop,
  slotProps,
  emptyStateSlot,
}: CommentsTableListProps) => {
  const theme = useTheme();
  const anchorRef = useRef(null);
  const [open, setOpen] = useState(false);

  const handleOpen = () => setOpen(true);
  const handleClose = () => setOpen(false);

  const handleMenuItemClick = (option: FilterOption) => {
    setOpen(false);
    onFilterChange?.(option);
  };

  const filterColors = getFilterColors(selectedFilter, theme);

  const columns = useMemo<Column[]>(
    () => [
      {
        id: 'score',
        heading: columnHeadings.score,
        width: '10%',
        renderCell: (row: CommentData) => row.score,
      },
      {
        id: 'comment',
        heading: columnHeadings.comment,
        width: '90%',
        renderCell: (row: CommentData) => (
          <Title
            title={row.comment}
            fontWeight="fontWeightRegular"
            variant="S"
          />
        ),
      },
    ],
    [columnHeadings],
  );

  return (
    <CardContainer
      sx={{
        [`& .${cardContentClasses.root}`]: {
          display: 'flex',
          flexDirection: 'column',
          gap: 2,
          flexShrink: 0,
        },
      }}
      fullWidth
    >
      <CardContainer
        color="grey"
        fullWidth
      >
        <Stack
          sx={{
            flexDirection: 'row',
            alignItems: 'center',
            gap: 2,
          }}
        >
          <Title
            title={title}
            variant="L"
          />
          <Button
            ref={anchorRef}
            onClick={handleOpen}
            variant="secondary"
            endIcon={<IconChevronDown size={20} />}
          >
            {filterLabels[selectedFilter].label}
          </Button>
          <Menu
            open={open}
            anchorEl={anchorRef.current}
            onClose={handleClose}
            position="right"
          >
            {filterOptions.map(option => (
              <MenuItem
                key={option}
                selected={option === selectedFilter}
                onClick={() => handleMenuItemClick(option)}
              >
                <Typography
                  variant="inherit"
                  noWrap
                >
                  {filterLabels[option].label}
                </Typography>
              </MenuItem>
            ))}
          </Menu>
        </Stack>
      </CardContainer>
      <Fade
        in={!loading && data.length > 0 && !!filterColors}
        unmountOnExit
        timeout={{ enter: 225, exit: 0 }}
      >
        <div>
          {filterColors && (
            <TableFilterDecorator
              backgroundColor={filterColors.backgroundColor}
              textColor={filterColors.textColor}
              title={filterLabels[selectedFilter].label}
              description={filterLabels[selectedFilter].description}
              icon={filterColors.icon}
            />
          )}
        </div>
      </Fade>
      {!loading && data.length === 0 && emptyStateSlot && emptyStateSlot}
      {(loading || data.length > 0) && (
        <Stack
          {...slotProps?.tableWrapper}
          sx={{
            overflowY: 'auto',
            gap: 2,
            borderRadius: '16px',
            ...slotProps?.tableWrapper?.sx,
          }}
        >
          <TableContainer
            sx={{
              opacity: isPreviousData ? 0.5 : 1,
              overflow: 'hidden',
            }}
          >
            <Table>
              <TableHead>
                <TableRow headerRow>
                  {columns.map(column => (
                    <TableCell
                      key={column.id}
                      headerCell
                      sx={{ width: column.width }}
                    >
                      {column.heading}
                    </TableCell>
                  ))}
                </TableRow>
              </TableHead>
              <TableBody>
                {loading &&
                  times(INITIAL_SKELETON_ROWS, index => (
                    <CommentListRowSkeleton key={index} />
                  ))}
                {!loading &&
                  data.map((row, index) => (
                    <TableRow key={index}>
                      {columns.map(column => (
                        <TableCell key={column.id}>
                          {column.renderCell(row)}
                        </TableCell>
                      ))}
                    </TableRow>
                  ))}
                {!loading &&
                  loadingMore &&
                  times(LOADING_MORE_SKELETON_ROWS, index => (
                    <CommentListRowSkeleton key={`loading-more-${index}`} />
                  ))}
              </TableBody>
            </Table>
          </TableContainer>
          {onLoadMore && onScrollToTop && (
            <TableLoader
              loadedCount={loadedCount}
              totalCount={totalCount}
              onLoadMore={onLoadMore}
              onScrollToTop={onScrollToTop}
            />
          )}
        </Stack>
      )}
    </CardContainer>
  );
};

export default CommentsTableList;
