import PageLoader from 'components/common/PageLoader/PageLoader';
import { Table } from 'components/common/table/Table/Table.styled';
import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
import { SeekDirection, TopicMessage } from 'generated-sources';
import styled from 'styled-components';
import { compact, concat, groupBy, map, maxBy, minBy } from 'lodash';
import React, { useContext } from 'react';
import { useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import {
  getTopicMessges,
  getIsTopicMessagesFetching,
} from 'redux/reducers/topicMessages/selectors';
import TopicMessagesContext from 'components/contexts/TopicMessagesContext';

import Message from './Message';
import * as S from './MessageContent/MessageContent.styled';

const MessagesPaginationWrapperStyled = styled.div`
  padding: 16px;
  display: flex;
  justify-content: flex-start;
`;

const MessagesTable: React.FC = () => {
  const history = useHistory();

  const { searchParams, isLive } = useContext(TopicMessagesContext);

  const messages = useSelector(getTopicMessges);
  const isFetching = useSelector(getIsTopicMessagesFetching);

  const handleNextClick = () => {
    const seekTo = searchParams.get('seekTo');

    if (seekTo) {
      const selectedPartitions = seekTo.split(',').map((item) => {
        const [partition] = item.split('::');
        return { offset: 0, partition: parseInt(partition, 10) };
      });

      const seekDirection = searchParams.get('seekDirection');
      const isBackward = seekDirection === SeekDirection.BACKWARD;

      const messageUniqs = map(groupBy(messages, 'partition'), (v) =>
        isBackward ? minBy(v, 'offset') : maxBy(v, 'offset')
      ).map((message) => ({
        offset: message?.offset || 0,
        partition: message?.partition || 0,
      }));

      const nextSeekTo = compact(
        map(
          groupBy(concat(selectedPartitions, messageUniqs), 'partition'),
          (v) => maxBy(v, 'offset')
        )
      )
        .map(({ offset, partition }) => {
          const offsetQuery = isBackward ? offset : offset + 1;

          return `${partition}::${offsetQuery}`;
        })
        .join(',');

      searchParams.set('seekTo', nextSeekTo);

      history.push({
        search: `?${searchParams.toString()}`,
      });
    }
  };

  return (
    <>
      <Table isFullwidth>
        <thead>
          <tr>
            <TableHeaderCell> </TableHeaderCell>
            <TableHeaderCell title="Offset" />
            <TableHeaderCell title="Partition" />
            <TableHeaderCell title="Timestamp" />
            <TableHeaderCell title="Key" />
            <TableHeaderCell title="Content" />
            <TableHeaderCell> </TableHeaderCell>
          </tr>
        </thead>
        <tbody>
          {messages.map((message: TopicMessage) => (
            <Message
              key={[
                message.offset,
                message.timestamp,
                message.key,
                message.partition,
              ].join('-')}
              message={message}
            />
          ))}
          {isFetching && isLive && !messages.length && (
            <tr>
              <td colSpan={10}>
                <PageLoader />
              </td>
            </tr>
          )}
          {messages.length === 0 && !isFetching && (
            <tr>
              <td colSpan={10}>No messages found</td>
            </tr>
          )}
        </tbody>
      </Table>
      {!isLive && (
        <MessagesPaginationWrapperStyled>
          <S.PaginationButton onClick={handleNextClick}>
            Next
          </S.PaginationButton>
        </MessagesPaginationWrapperStyled>
      )}
    </>
  );
};

export default MessagesTable;
