import { Injectable, Logger, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { Kafka, Producer } from 'kafkajs';
import {
  UserRegisteredEvent,
  UserLoggedInEvent,
  UserLoggedOutEvent,
  PasswordChangedEvent,
  AccountLockedEvent,
  PhoneChangedEvent,
  PasswordResetEvent,
} from '../../domain/events/auth.events';

/**
 * Event publisher — 直接发布到 Kafka (fire-and-forget, Kafka 不可用时静默丢弃)
 * 生产环境可改为 Outbox pattern 保证 at-least-once 语义
 */
@Injectable()
export class EventPublisherService implements OnModuleInit, OnModuleDestroy {
  private readonly logger = new Logger(EventPublisherService.name);
  private producer: Producer | null = null;
  private connected = false;

  async onModuleInit() {
    const brokers = (process.env.KAFKA_BROKERS || 'localhost:9092').split(',').map((b) => b.trim());
    try {
      const kafka = new Kafka({ clientId: 'auth-service', brokers, retry: { retries: 3 } });
      this.producer = kafka.producer({ idempotent: false });
      await this.producer.connect();
      this.connected = true;
      this.logger.log(`Kafka producer connected [${brokers.join(', ')}]`);
    } catch (err) {
      this.logger.warn(`Kafka 不可用，事件将被丢弃: ${err.message}`);
    }
  }

  async onModuleDestroy() {
    if (this.connected && this.producer) {
      await this.producer.disconnect();
    }
  }

  async publishUserRegistered(event: UserRegisteredEvent): Promise<void> {
    await this.publish('genex.user.registered', event.userId, 'user.registered', event);
  }

  async publishUserLoggedIn(event: UserLoggedInEvent): Promise<void> {
    await this.publish('genex.user.logged-in', event.userId, 'user.logged_in', event);
  }

  async publishUserLoggedOut(event: UserLoggedOutEvent): Promise<void> {
    await this.publish('genex.user.logged-out', event.userId, 'user.logged_out', event);
  }

  async publishPasswordChanged(event: PasswordChangedEvent): Promise<void> {
    await this.publish('genex.user.password-changed', event.userId, 'user.password_changed', event);
  }

  async publishAccountLocked(event: AccountLockedEvent): Promise<void> {
    await this.publish('genex.user.locked', event.userId, 'user.account_locked', event);
  }

  async publishPhoneChanged(event: PhoneChangedEvent): Promise<void> {
    await this.publish('genex.user.phone-changed', event.userId, 'user.phone_changed', event);
  }

  async publishPasswordReset(event: PasswordResetEvent): Promise<void> {
    await this.publish('genex.user.password-reset', event.userId, 'user.password_reset', event);
  }

  private async publish(topic: string, key: string, eventType: string, payload: any): Promise<void> {
    if (!this.connected || !this.producer) return;
    try {
      await this.producer.send({
        topic,
        messages: [{
          key,
          value: JSON.stringify(payload),
          headers: { eventType, timestamp: new Date().toISOString(), source: 'auth-service' },
        }],
      });
    } catch (err) {
      this.logger.warn(`事件发布失败 topic=${topic}: ${err.message}`);
    }
  }
}
