import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, LessThan } from 'typeorm';
import { ProcessedEvent } from './processed-event.entity';

/**
 * Idempotency Service - ensures Kafka events are processed exactly once.
 * 24-hour idempotency window: consumers can safely retry within this window.
 *
 * Usage in Kafka consumer:
 *   const eventId = message.headers.eventId;
 *   if (await idempotencyService.isProcessed(eventId, 'my-consumer-group')) return;
 *   // ... process event ...
 *   await idempotencyService.markProcessed(eventId, 'my-consumer-group');
 */
@Injectable()
export class IdempotencyService {
  private readonly logger = new Logger('Idempotency');

  constructor(
    @InjectRepository(ProcessedEvent)
    private readonly processedRepo: Repository<ProcessedEvent>,
  ) {}

  /**
   * Check if an event has already been processed by this consumer group.
   */
  async isProcessed(eventId: string, consumerGroup: string): Promise<boolean> {
    const existing = await this.processedRepo.findOne({
      where: { eventId, consumerGroup },
    });
    return !!existing;
  }

  /**
   * Mark an event as processed. Sets 24h expiry for cleanup.
   */
  async markProcessed(eventId: string, consumerGroup: string): Promise<void> {
    const record = this.processedRepo.create({
      eventId,
      consumerGroup,
      expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000),
    });
    await this.processedRepo.save(record);
  }

  /**
   * Cleanup expired processed events (run daily via cron).
   */
  async cleanupExpired(): Promise<number> {
    const result = await this.processedRepo.delete({
      expiresAt: LessThan(new Date()),
    });
    const count = result.affected || 0;
    if (count > 0) {
      this.logger.log(`Cleaned up ${count} expired processed events`);
    }
    return count;
  }
}
