import { Controller, Logger } from '@nestjs/common';
import { MessagePattern, Payload, Ctx, KafkaContext } from '@nestjs/microservices';
import { OutboxRepository } from '../persistence/repositories/outbox.repository';

/**
 * 事件确认消息结构
 */
interface EventAckMessage {
  /** 原始事件的 aggregateId */
  eventId: string;
  /** 原始事件类型 */
  eventType: string;
  /** 消费服务名称 */
  consumerService: string;
  /** 处理结果 */
  success: boolean;
  /** 错误信息（如果失败） */
  error?: string;
  /** 确认时间 */
  confirmedAt: string;
}

/**
 * 事件确认 Kafka 控制器
 *
 * B方案核心组件：监听消费方(wallet-service)的确认事件
 * 使用 @MessagePattern 装饰器来处理 Kafka 消息
 */
@Controller()
export class EventAckController {
  private readonly logger = new Logger(EventAckController.name);

  constructor(private readonly outboxRepository: OutboxRepository) {}

  /**
   * 处理事件确认消息
   *
   * 消费方 (wallet-service) 成功处理事件后，会发送确认消息到此 topic
   */
  @MessagePattern('reward.events.ack')
  async handleEventAck(
    @Payload() message: EventAckMessage,
    @Ctx() context: KafkaContext,
  ): Promise<void> {
    const partition = context.getPartition();
    const offset = context.getMessage().offset;

    this.logger.debug(
      `[ACK] Received ack from ${message.consumerService} for event ${message.eventId} ` +
      `[partition=${partition}, offset=${offset}]`,
    );

    try {
      if (message.success) {
        // 标记事件为已确认（使用 eventId + eventType 精确匹配）
        const confirmed = await this.outboxRepository.markAsConfirmed(
          message.eventId,
          message.eventType,
        );

        if (confirmed) {
          this.logger.log(
            `[ACK] ✓ Event ${message.eventId} (${message.eventType}) confirmed by ${message.consumerService}`,
          );
        } else {
          this.logger.warn(
            `[ACK] Event ${message.eventId} (${message.eventType}) not found or already confirmed`,
          );
        }
      } else {
        // 消费方处理失败
        this.logger.warn(
          `[ACK] ✗ Event ${message.eventId} failed in ${message.consumerService}: ${message.error}`,
        );
        // 不改变状态，等待超时重发
      }
    } catch (error) {
      this.logger.error(
        `[ACK] Error processing ack for event ${message.eventId}:`,
        error,
      );
    }
  }
}
