import { useIntl } from 'react-intl';
import TableCell from './TableCell';
import TableHeader, { TableHeaderType } from './TableHeader';
import TableRow, { TableRowClickableType, TableRowType } from './TableRow';
import { InfoPrompt } from '../prompt/InfoPrompt';

import messages from './Table.messages';
import Loader from '../loader';
import { Sentiment, Size } from '../common';
import StatusIcon from '../statusIcon';
import { clsx } from 'clsx';
import { useTheme } from '@wise/components-theming';
import Body from '../body';

export interface TableProps {
  'aria-labelledby'?: string;
  data: {
    headers?: TableHeaderType[];
    rows?: TableRowType[] | TableRowClickableType[];
    onRowClick?: (rowData: TableRowType | TableRowClickableType) => void;
  };
  loading?: boolean;
  className?: string | undefined;
  fullWidth?: boolean;
  error?: {
    message?: string;
    action?: {
      href?: string;
      text?: string;
    };
  };
}

const Table = ({
  'aria-labelledby': ariaLabelledBy,
  data,
  loading,
  className,
  fullWidth = true,
  error,
}: TableProps) => {
  const { formatMessage } = useIntl();
  const { theme } = useTheme();
  const isEmptyHeader = loading ?? (data?.headers && !data?.headers.length);

  const getRowLength = () => {
    const columnsLength = data?.headers?.length ?? 0;
    return data?.onRowClick ? columnsLength + 1 : columnsLength;
  };

  const getTableContent = () => {
    if (loading) {
      return (
        <TableRow>
          <TableCell>
            <Loader data-testid="np-table-loader" />
          </TableCell>
        </TableRow>
      );
    }

    // Shows the `emptyData` message when there is no data to display
    if (!data?.rows?.length) {
      return (
        <TableRow>
          <TableCell colSpan={data?.headers?.length}>
            <div className="np-table-empty-data" data-testid="np-table-empty-data">
              <StatusIcon sentiment={Sentiment.WARNING} size={Size.MEDIUM} />
              <Body type="body-default-bold">{formatMessage(messages.emptyData)}</Body>
            </div>
          </TableCell>
        </TableRow>
      );
    }

    return data?.rows?.map((rowData, rowIndex) => {
      return (
        <TableRow
          key={'table-row-'.concat(rowIndex.toString())}
          rowData={rowData}
          hasSeparator={data?.rows?.length ? data.rows.length - 1 !== rowIndex : false}
          onRowClick={data?.onRowClick}
        />
      );
    });
  };

  if (error) {
    return (
      <InfoPrompt
        className="np-table-error"
        aria-live="assertive"
        description={error.message ?? ''}
        sentiment="negative"
        action={{
          href: error?.action?.href ?? '/',
          label: error?.action?.text ?? formatMessage(messages.refreshPage),
        }}
        data-testid="np-table-error"
      />
    );
  }

  return (
    <>
      <div aria-live="polite" className="sr-only">
        {formatMessage(messages[loading ? 'loading' : 'loaded'])}
      </div>
      <div
        role={loading ? 'presentation' : 'region'}
        aria-labelledby={ariaLabelledBy}
        className={clsx('np-table-outer-container', className, {
          'np-theme-personal': theme === 'bright-green',
          'np-table-outer-container--center': !fullWidth,
          'np-table-outer-container--full-width': fullWidth,
        })}
        tabIndex={0}
        data-testid="np-table-outer-container"
      >
        <div
          className={clsx('np-table-container', {
            'np-table-container--loading': loading,
          })}
          data-testid="np-table-container"
        >
          <div className="np-table-inner-container">
            <table className="np-table">
              <thead aria-hidden={isEmptyHeader}>
                <tr>
                  {isEmptyHeader ? (
                    <TableHeader />
                  ) : (
                    data?.headers?.map((headerItem: TableHeaderType, index) => (
                      <TableHeader
                        key={headerItem.header?.concat(index.toString())}
                        {...headerItem}
                      />
                    ))
                  )}
                  {data?.onRowClick && <TableHeader isActionHeader />}
                </tr>
              </thead>
              <tbody>
                <tr
                  key="first-np-table-row--cosmetic"
                  aria-hidden="true"
                  className="np-table-row np-table-row--cosmetic"
                >
                  <td className="np-table-cell" colSpan={getRowLength()} />
                </tr>
                {getTableContent()}
                <tr
                  key="last-np-table-row--cosmetic"
                  aria-hidden="true"
                  className="np-table-row np-table-row--cosmetic"
                >
                  <td className="np-table-cell" colSpan={getRowLength()} />
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </>
  );
};

export default Table;
