import { DataSource } from 'typeorm';
import { MessageEntity } from '../../../entities';
import { replaceMessageReactions } from '../../relations';
import { UpdateMessageCommand } from '../../types';
import { getCurrentUserScope } from '../../current-user-scope';

export async function handleUpdateMessage(command: UpdateMessageCommand, dataSource: DataSource): Promise<void> {
  const { messageId, updates } = command.payload;

  await dataSource.transaction(async (manager) => {
    const currentUserId = await getCurrentUserScope(manager);

    if (!currentUserId) {
      return;
    }

    const repo = manager.getRepository(MessageEntity);
    const existing = await repo.findOne({ where: { id: messageId, ownerUserId: currentUserId } });

    if (!existing)
      return;

    const directFields = [
      'senderId',
      'senderName',
      'content',
      'timestamp'
    ] as const;
    const entity = existing as unknown as Record<string, unknown>;

    for (const field of directFields) {
      if (updates[field] !== undefined)
        entity[field] = updates[field];
    }

    const nullableFields = [
      'channelId',
      'editedAt',
      'replyToId',
      'headHash'
    ] as const;

    for (const field of nullableFields) {
      if (updates[field] !== undefined)
        entity[field] = updates[field] ?? null;
    }

    if (updates.revision !== undefined) {
      existing.revision = updates.revision;
    }

    if (updates.isDeleted !== undefined) {
      existing.isDeleted = updates.isDeleted ? 1 : 0;
    }

    if (updates.linkMetadata !== undefined)
      existing.linkMetadata = updates.linkMetadata ? JSON.stringify(updates.linkMetadata) : null;

    await repo.save(existing);

    if (updates.reactions !== undefined) {
      await replaceMessageReactions(manager, messageId, updates.reactions ?? []);
    }
  });
}
