import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { TenantAwareRepository } from '@it0/database';
import { ConversationMessage } from '../../domain/entities/conversation-message.entity';

@Injectable()
export class MessageRepository extends TenantAwareRepository<ConversationMessage> {
  constructor(dataSource: DataSource) {
    super(dataSource, ConversationMessage);
  }

  async findBySessionId(
    sessionId: string,
    limit = 20,
    offset = 0,
  ): Promise<ConversationMessage[]> {
    return this.withRepository((repo) =>
      repo.find({
        where: { sessionId } as any,
        order: { sequenceNumber: 'ASC' },
        skip: offset,
        take: limit,
      }),
    );
  }

  /**
   * Load the most recent N messages for a session, ordered by sequence number ASC.
   */
  async findRecentBySessionId(
    sessionId: string,
    limit = 20,
  ): Promise<ConversationMessage[]> {
    return this.withRepository(async (repo) => {
      // Subquery approach: get the last N messages ordered DESC, then re-order ASC
      const messages = await repo.find({
        where: { sessionId } as any,
        order: { sequenceNumber: 'DESC' },
        take: limit,
      });
      return messages.reverse();
    });
  }

  async countBySessionId(sessionId: string): Promise<number> {
    return this.withRepository((repo) =>
      repo.count({ where: { sessionId } as any }),
    );
  }

  async getNextSequenceNumber(sessionId: string): Promise<number> {
    return this.withRepository(async (repo) => {
      const result = await repo
        .createQueryBuilder('msg')
        .select('COALESCE(MAX(msg.sequence_number), 0)', 'maxSeq')
        .where('msg.session_id = :sessionId', { sessionId })
        .getRawOne();
      return (parseInt(result?.maxSeq ?? '0', 10)) + 1;
    });
  }

  async deleteBySessionId(sessionId: string): Promise<void> {
    await this.withRepository(async (repo) => {
      await repo.delete({ sessionId } as any);
      return undefined as any;
    });
  }
}
