import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import classNames from 'clsx';
import NextLink from 'next/link';
import { InfoOutlined } from '@mui/icons-material';

import { SORT_DESC } from '@/modules/@common/constants/sort';
import { CUSTOM_PARENT_STICKY_CLASS_NAME } from '@/modules/marketplace/common/constants';

import { resolveObjectPath } from '../helpers';
import { getNumberInRange } from '@/modules/@common/helpers/number';

import {
  Checkbox,
  CircularProgress,
  Stack,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TablePagination,
  TableRow,
  TableScroll,
  TableSortLabel,
  Tooltip,
  Typography,
} from '@/mui/components';

import styles from './Table.module.scss';

function AccountsTable({
  sortBy = '',
  sortOrder = 'ASC',
  handleSorting = () => {},
  selecting = false,
  selected = [],
  setSelected = () => {},
  cellRenderer = null,
  withPagination = true,
  onChangePage = () => {},
  setRowsPerPage = () => {},
  createRowLink = () => {},
  page = 1,
  rowsPerPage = 0,
  totalCount = 0,
  rowsPerPageOptions = [],
  setRowBackgroundBy = () => null,
  stopRefreshInterval = null,
  resetRefreshInterval = null,
  isOpenNewTab = false,
  isLoading = false,
  onScroll = null,
  ...props
}) {
  const handleSelectAllClick = (event) => {
    if (event.target.checked) {
      const newSelecteds = props.rows.map((item) => item.id);
      setSelected(newSelecteds);
      return;
    }
    setSelected([]);
  };

  const handleSelect = (id) => {
    const selectedIndex = selected.indexOf(id);
    let newSelected = [];

    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, id);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(selected.slice(0, selectedIndex), selected.slice(selectedIndex + 1));
    }

    setSelected(newSelected);
  };

  const isSelected = (id) => selected.indexOf(id) !== -1;

  const tableRef = useRef(null);
  const tableHeaderRef = useRef(null);

  useEffect(() => {
    const step = (event) => {
      if (tableHeaderRef.current && tableRef.current) {
        const top = getNumberInRange(
          (tableRef.current.getBoundingClientRect().y - (event.target.getBoundingClientRect?.().y ?? 0)) * -1,
          0,
          tableRef.current.clientHeight - tableHeaderRef.current.clientHeight * 2,
        );

        tableHeaderRef.current.style.transform = `translateY(${top}px)`;
      }
    };

    const subscribeParent = tableRef.current.closest(`.${CUSTOM_PARENT_STICKY_CLASS_NAME}`) || document;

    subscribeParent.addEventListener('scroll', step);

    return () => {
      subscribeParent.removeEventListener('scroll', step);
    };
  }, [tableRef.current, tableHeaderRef.current]);

  return (
    <TableContainer>
      <TableScroll inverseScroll onScroll={onScroll}>
        <Table ref={tableRef} aria-label="table" size="small" className={styles.Table}>
          <TableHead ref={tableHeaderRef}>
            <TableRow>
              {selecting && (
                <TableCell padding="checkbox" align="center">
                  <div className={styles.CheckboxWrap}>
                    <Checkbox
                      indeterminate={selected?.length && selected?.length < props.rows?.length}
                      checked={props.rows.length && selected?.length === props.rows?.length}
                      onChange={handleSelectAllClick}
                      inputProps={{ 'aria-label': 'select all desserts' }}
                    />
                  </div>
                </TableCell>
              )}
              {props.headers.map((header) => {
                const defaultSortOrder = header.defaultSortOrder ?? SORT_DESC;
                if (header.withGap) {
                  return (
                    <React.Fragment key={header.id}>
                      <TableCell
                        key={header.id}
                        className={styles.Cell}
                        align={header.align ?? 'left'}
                        width={header.width ?? ''}
                      >
                        {header.isSortable && (
                          <TableSortLabel
                            active={sortBy === header.id}
                            direction={sortBy === header.id ? sortOrder?.toLowerCase() : defaultSortOrder}
                            onClick={() => {
                              handleSorting(header.id);
                            }}
                            hideSortIcon
                          >
                            {header.label}
                            {sortBy === header.id ? (
                              <span className={styles.VisuallyHidden}>
                                {sortOrder === SORT_DESC ? 'sorted descending' : 'sorted ascending'}
                              </span>
                            ) : null}
                          </TableSortLabel>
                        )}

                        {!header.isSortable && header.label}
                      </TableCell>
                      <TableCell key={`${header.id}-percent`} />
                    </React.Fragment>
                  );
                }

                return (
                  <TableCell
                    key={header.id}
                    align={header.align ?? 'left'}
                    width={header.width ?? ''}
                    className={styles.Cell}
                  >
                    {header.isSortable && (
                      <TableSortLabel
                        active={sortBy === header.id}
                        direction={sortBy === header.id ? sortOrder?.toLowerCase() : defaultSortOrder}
                        onClick={() => {
                          handleSorting(header.id);
                        }}
                        hideSortIcon
                      >
                        {header.label}
                        {sortBy === header.id ? (
                          <span className={styles.VisuallyHidden}>
                            {sortOrder === 'DESC' ? 'sorted descending' : 'sorted ascending'}
                          </span>
                        ) : null}
                      </TableSortLabel>
                    )}

                    {!header.isSortable && header.label}
                  </TableCell>
                );
              })}
            </TableRow>
          </TableHead>
          <TableBody className={styles.TableBody}>
            {props.rows.map((row, index) => {
              const link = createRowLink(row);

              return (
                <TableRow
                  key={row.id}
                  className={classNames(styles.Row, setRowBackgroundBy && setRowBackgroundBy(row))}
                  component={link ? NextLink : 'tr'}
                  href={link}
                  target={link && isOpenNewTab ? '_blank' : null}
                >
                  {selecting && (
                    <TableCell padding="checkbox" align="center">
                      <div
                        className={styles.CheckboxWrap}
                        onClick={(e) => {
                          e.stopPropagation();
                          e.preventDefault();
                        }}
                        aria-hidden="true"
                      >
                        <Checkbox
                          checked={isSelected(row.id)}
                          onChange={() => {
                            handleSelect(row.id);
                          }}
                          inputProps={{ 'aria-labelledby': `enhanced-table-checkbox-${index}` }}
                          onClick={(e) => e.stopPropagation()}
                          disabled={row.compressed}
                        />
                      </div>
                    </TableCell>
                  )}

                  {props.cells.map(
                    ({
                      key,
                      align,
                      prefix: prefixConfig,
                      postfix: postfixConfig,
                      needMultiply: needMultiplyConfig,
                      withPercent,
                      emptyMask,
                    }) => {
                      const cell = resolveObjectPath(row, key);
                      let needMultiply = needMultiplyConfig;
                      let prefix = prefixConfig;
                      let postfix = postfixConfig;

                      if (key === 'pricing' && cell?.model === 'REV_SHARE') {
                        prefix = '';
                        postfix = '%';
                        needMultiply = true;
                      }

                      const cellValue = needMultiply ? (cell?.value ?? 0) * 100 : cell?.value;

                      const value = cellValue?.toLocaleString(undefined, {
                        minimumFractionDigits: prefix?.length || postfix?.length ? 2 : 0,
                        maximumFractionDigits: 2,
                      });

                      if (cellRenderer?.[key]) {
                        const renderFn = cellRenderer[key];
                        if (typeof renderFn === 'function') {
                          return (
                            <TableCell key={key} align={align ?? 'left'} className={styles.Cell}>
                              {renderFn({
                                cell,
                                id: row.id,
                                row,
                                stopRefreshInterval,
                                resetRefreshInterval,
                              })}
                            </TableCell>
                          );
                        }
                      }

                      if (cell === undefined || cell === null) {
                        if (withPercent) {
                          return (
                            <React.Fragment key={key}>
                              <TableCell key={key} className={styles.Cell} />
                              <TableCell key={`${key}-percent`} className={styles.Cell} />
                            </React.Fragment>
                          );
                        }
                        return (
                          <TableCell key={key} className={styles.Cell}>
                            {emptyMask ?? ''}
                          </TableCell>
                        );
                      }

                      if (withPercent) {
                        const percent = cell?.change;
                        // todo: it has to be split and replaced,
                        // (apsInfo | profitDecreased) works only for REQUESTS cell (look at getData epic in account)
                        const apsInfo = !!cell?.apsInfo;
                        const profitDecreased = cell?.profitDecreased;
                        const roundedPercent = percent ? Math.round(percent * 100) : 0;
                        const percentFormatted = roundedPercent > 0 ? `+${roundedPercent}%` : `${roundedPercent}%`;

                        return (
                          <React.Fragment key={key}>
                            <TableCell
                              key={key}
                              align={align ?? 'left'}
                              className={classNames(styles.Cell, {
                                [styles.Cell___red]: profitDecreased,
                              })}
                            >
                              <Stack
                                spacing={1}
                                direction="row"
                                alignItems="center"
                                justifyContent="flex-end"
                                fullWidth
                              >
                                {apsInfo && (
                                  <Tooltip title="For Amazon/APS tags, only responses with an actual bid are counted as requests, so this demand typically shows fewer requests than other partners">
                                    <InfoOutlined fontSize="x2Small" htmlColor="info.main" />
                                  </Tooltip>
                                )}
                                <Typography>
                                  {`${value?.charAt(0) === '-' ? '-' : ''}${
                                    prefix ?? ''
                                  }${value?.replace('-', '') ?? ''}${postfix ?? ''}`}
                                </Typography>
                              </Stack>
                            </TableCell>
                            <TableCell key={`${key}-percent`} className={styles.Cell}>
                              <span
                                className={classNames(styles.Percent, {
                                  [styles.Percent___increased]: roundedPercent > 0,
                                  [styles.Percent___decreased]: roundedPercent < 0,
                                })}
                              >
                                {!Number.isNaN(parseInt(percent, 10)) ? percentFormatted : ''}
                              </span>
                            </TableCell>
                          </React.Fragment>
                        );
                      }

                      return (
                        <TableCell key={key} align={align ?? 'left'} className={styles.Cell}>
                          {`${value?.charAt(0) === '-' ? '-' : ''}${prefix ?? ''}${
                            value?.replace('-', '') ??
                            cell?.toLocaleString(undefined, {
                              minimumFractionDigits: 0,
                              maximumFractionDigits: 2,
                            })
                          }${postfix ?? ''}`}
                        </TableCell>
                      );
                    },
                  )}
                </TableRow>
              );
            })}
            {isLoading && <div className={styles.LoaderOverlay} />}
          </TableBody>
        </Table>
        {isLoading && (
          <div className={styles.Loader}>
            <CircularProgress size="x2Large" />
          </div>
        )}
      </TableScroll>
      {withPagination && (
        <TablePagination
          component="div"
          size="small"
          rowsPerPageOptions={rowsPerPageOptions}
          count={totalCount}
          rowsPerPage={rowsPerPage}
          page={page + 1}
          onPageChange={(event, page$) => {
            onChangePage(page$ - 1);
            if (resetRefreshInterval) {
              resetRefreshInterval();
            }
          }}
          onRowsPerPageChange={(event) => {
            setRowsPerPage(+event.target.value);
            if (resetRefreshInterval) {
              resetRefreshInterval();
            }
          }}
        />
      )}
    </TableContainer>
  );
}

AccountsTable.propTypes = {
  headers: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  rows: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  cells: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  sortBy: PropTypes.string,
  sortOrder: PropTypes.string,
  handleSorting: PropTypes.func,
  selecting: PropTypes.bool,
  selected: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.shape({})])),
  setSelected: PropTypes.func,
  cellRenderer: PropTypes.shape({}),
  withPagination: PropTypes.bool,
  onChangePage: PropTypes.func,
  setRowsPerPage: PropTypes.func,
  page: PropTypes.number,
  rowsPerPage: PropTypes.number,
  totalCount: PropTypes.number,
  rowsPerPageOptions: PropTypes.arrayOf(PropTypes.number),
  createRowLink: PropTypes.func,
  setRowBackgroundBy: PropTypes.func,
  stopRefreshInterval: PropTypes.func,
  resetRefreshInterval: PropTypes.func,
  isOpenNewTab: PropTypes.bool,
  isLoading: PropTypes.bool,
  onScroll: PropTypes.func,
};

export default AccountsTable;
