import { Inject, Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { LoggerService } from '@modules/shared';
import { type ListingApprovedEvent } from '../../domain/events/listing-approved.event';
import { type ListingRejectedEvent } from '../../domain/events/listing-rejected.event';
import {
  MODERATION_AUDIT_LOG_REPOSITORY,
  type CreateModerationAuditLogInput,
  type IModerationAuditLogRepository,
} from '../../domain/repositories/moderation-audit-log.repository';

/**
 * Write-side hook that records every moderation action into
 * `ModerationAuditLog`. It listens to domain events published by the existing
 * moderation command handlers (approve/reject/bulk) so the public API of those
 * handlers stays unchanged, per TEC-2926.
 *
 * Failures are swallowed (logged only) so an audit write never breaks the
 * primary moderation flow.
 */
@Injectable()
export class ModerationAuditListener {
  constructor(
    @Inject(MODERATION_AUDIT_LOG_REPOSITORY)
    private readonly moderationAuditRepo: IModerationAuditLogRepository,
    private readonly logger: LoggerService,
  ) {}

  @OnEvent('listing.approved_by_admin', { async: true })
  async onListingApproved(event: ListingApprovedEvent): Promise<void> {
    await this.write({
      targetType: 'listing',
      targetId: event.aggregateId,
      action: 'approve',
      moderatorId: event.adminId,
      reason: event.moderationNotes,
      metadata: event.moderationNotes
        ? { moderationNotes: event.moderationNotes }
        : undefined,
    });
  }

  @OnEvent('listing.rejected_by_admin', { async: true })
  async onListingRejected(event: ListingRejectedEvent): Promise<void> {
    await this.write({
      targetType: 'listing',
      targetId: event.aggregateId,
      action: 'reject',
      moderatorId: event.adminId,
      reason: event.reason,
      metadata: { reason: event.reason },
    });
  }

  private async write(input: CreateModerationAuditLogInput): Promise<void> {
    try {
      await this.moderationAuditRepo.create(input);
      this.logger.log(
        `Moderation audit: ${input.action} by ${input.moderatorId} on ${input.targetType}:${input.targetId}`,
        'ModerationAuditListener',
      );
    } catch (error) {
      this.logger.error(
        `Failed to write moderation audit log: ${input.action} by ${input.moderatorId} on ${input.targetType}:${input.targetId}`,
        error instanceof Error ? error.stack : String(error),
        'ModerationAuditListener',
      );
    }
  }
}
