import { Injectable, Logger, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Kafka, Producer, logLevel } from 'kafkajs';
import { DomainEvent } from '@/domain/events/domain-event.base';

@Injectable()
export class EventPublisherService implements OnModuleInit, OnModuleDestroy {
  private readonly logger = new Logger(EventPublisherService.name);
  private readonly kafka: Kafka;
  private readonly producer: Producer;

  constructor(private readonly configService: ConfigService) {
    this.kafka = new Kafka({
      clientId: this.configService.get<string>('kafka.clientId'),
      brokers: this.configService.get<string[]>('kafka.brokers') || ['localhost:9092'],
      logLevel: logLevel.WARN,
    });
    this.producer = this.kafka.producer();
  }

  async onModuleInit() {
    await this.producer.connect();
    this.logger.log('Kafka producer connected');
  }

  async onModuleDestroy() {
    await this.producer.disconnect();
    this.logger.log('Kafka producer disconnected');
  }

  /**
   * 发布领域事件
   */
  async publish(event: DomainEvent): Promise<void> {
    const topic = this.getTopicForEvent(event.eventType);
    const message = {
      key: event.eventId,
      value: JSON.stringify({
        eventId: event.eventId,
        eventType: event.eventType,
        occurredAt: event.occurredAt.toISOString(),
        payload: event.toPayload(),
      }),
      headers: {
        eventType: event.eventType,
        source: 'blockchain-service',
      },
    };

    await this.producer.send({
      topic,
      messages: [message],
    });

    this.logger.debug(`Published event: ${event.eventType} to topic: ${topic}`);
  }

  /**
   * 批量发布事件
   */
  async publishAll(events: DomainEvent[]): Promise<void> {
    for (const event of events) {
      await this.publish(event);
    }
  }

  /**
   * 发布原始事件数据（用于 Outbox 模式）
   */
  async publishRaw(event: {
    eventId: string;
    eventType: string;
    occurredAt: Date;
    payload: Record<string, unknown>;
  }): Promise<void> {
    const topic = this.getTopicForEvent(event.eventType);
    const message = {
      key: event.eventId,
      value: JSON.stringify({
        eventId: event.eventId,
        eventType: event.eventType,
        occurredAt: event.occurredAt.toISOString(),
        payload: event.payload,
      }),
      headers: {
        eventType: event.eventType,
        source: 'blockchain-service',
      },
    };

    await this.producer.send({
      topic,
      messages: [message],
    });

    this.logger.debug(`Published raw event: ${event.eventType} to topic: ${topic}`);
  }

  private getTopicForEvent(eventType: string): string {
    // 事件类型到 topic 的映射
    const topicMap: Record<string, string> = {
      'blockchain.deposit.detected': 'blockchain.deposits',
      'blockchain.deposit.confirmed': 'blockchain.deposits',
      'blockchain.wallet.address.created': 'blockchain.wallets',
      'blockchain.transaction.broadcasted': 'blockchain.transactions',
      // MPC 签名请求 - 发送到 mpc-service 消费的 topic
      'blockchain.mpc.signing.requested': 'mpc.SigningRequested',
    };
    return topicMap[eventType] || 'blockchain.events';
  }
}
