import { DataSource } from 'typeorm';
import { MessageEntity } from '../../../entities';
import { GetMessagesQuery } from '../../types';
import { rowToMessage } from '../../mappers';
import { loadMessageReactionsMap } from '../../relations';
import { getCurrentUserScope } from '../../current-user-scope';

export async function handleGetMessages(query: GetMessagesQuery, dataSource: DataSource) {
  const repo = dataSource.getRepository(MessageEntity);
  const { roomId, limit = 100, offset = 0, channelId, beforeTimestamp } = query.payload;
  const currentUserId = await getCurrentUserScope(dataSource);

  if (!currentUserId) {
    return [];
  }

  const rowsQuery = repo.createQueryBuilder('message')
    .where('message.roomId = :roomId', { roomId })
    .andWhere('message.ownerUserId = :currentUserId', { currentUserId })
    .orderBy('message.timestamp', 'DESC')
    .take(limit)
    .skip(offset);

  if (channelId === 'general') {
    rowsQuery.andWhere('(message.channelId = :channelId OR message.channelId IS NULL OR message.channelId = :emptyChannelId)', {
      channelId,
      emptyChannelId: ''
    });
  } else if (channelId) {
    rowsQuery.andWhere('message.channelId = :channelId', { channelId });
  }

  if (typeof beforeTimestamp === 'number') {
    rowsQuery.andWhere('message.timestamp < :beforeTimestamp', { beforeTimestamp });
  }

  const rows = await rowsQuery.getMany();
  const chronologicalRows = [...rows].reverse();
  const reactionsByMessageId = await loadMessageReactionsMap(dataSource, chronologicalRows.map((row) => row.id));

  return chronologicalRows.map((row) => rowToMessage(row, reactionsByMessageId.get(row.id) ?? []));
}
