import { Injectable, OnModuleInit, OnModuleDestroy, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Kafka, Producer, Consumer, EachMessagePayload } from 'kafkajs';

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

  constructor(private readonly configService: ConfigService) {
    const brokers = this.configService.get<string>('KAFKA_BROKERS', 'localhost:9092').split(',');
    const clientId = this.configService.get<string>('KAFKA_CLIENT_ID', 'leaderboard-service');

    this.kafka = new Kafka({
      clientId,
      brokers,
    });

    this.producer = this.kafka.producer();
    this.consumer = this.kafka.consumer({
      groupId: this.configService.get<string>('KAFKA_GROUP_ID', 'leaderboard-service-group'),
    });
  }

  async onModuleInit() {
    try {
      await this.producer.connect();
      await this.consumer.connect();
      this.isConnected = true;
      this.logger.log('Kafka 连接成功');
    } catch (error) {
      this.logger.warn('Kafka 连接失败，将在无消息队列模式下运行', error);
      this.isConnected = false;
    }
  }

  async onModuleDestroy() {
    if (this.isConnected) {
      await this.producer.disconnect();
      await this.consumer.disconnect();
    }
  }

  async publish(topic: string, message: any): Promise<void> {
    if (!this.isConnected) {
      this.logger.warn(`Kafka 未连接，跳过发布消息到 ${topic}`);
      return;
    }

    try {
      await this.producer.send({
        topic,
        messages: [
          {
            key: message.key || null,
            value: JSON.stringify(message),
          },
        ],
      });
      this.logger.debug(`消息已发布到 ${topic}`);
    } catch (error) {
      this.logger.error(`发布消息到 ${topic} 失败`, error);
    }
  }

  async subscribe(
    topics: string[],
    handler: (payload: EachMessagePayload) => Promise<void>,
  ): Promise<void> {
    if (!this.isConnected) {
      this.logger.warn('Kafka 未连接，跳过订阅');
      return;
    }

    try {
      for (const topic of topics) {
        await this.consumer.subscribe({ topic, fromBeginning: false });
      }

      await this.consumer.run({
        eachMessage: async (payload) => {
          try {
            await handler(payload);
          } catch (error) {
            this.logger.error(`处理消息失败: ${payload.topic}`, error);
          }
        },
      });

      this.logger.log(`已订阅 topics: ${topics.join(', ')}`);
    } catch (error) {
      this.logger.error('订阅 topics 失败', error);
    }
  }

  isKafkaConnected(): boolean {
    return this.isConnected;
  }
}
