import { Controller, Logger, OnModuleInit } from '@nestjs/common';
import { EventPattern, Payload } from '@nestjs/microservices';
import { RedisService } from '../../redis/redis.service';
import { ProcessedEventRepository } from '../../persistence/repositories/processed-event.repository';
import { UserWalletService } from '../../../application/services/user-wallet.service';
import { UserRegisteredEvent } from '../events/contribution-distribution.event';

// 4小时 TTL（秒）
const IDEMPOTENCY_TTL_SECONDS = 4 * 60 * 60;

@Controller()
export class UserRegisteredConsumer implements OnModuleInit {
  private readonly logger = new Logger(UserRegisteredConsumer.name);

  constructor(
    private readonly redis: RedisService,
    private readonly processedEventRepo: ProcessedEventRepository,
    private readonly userWalletService: UserWalletService,
  ) {}

  async onModuleInit() {
    this.logger.log('UserRegisteredConsumer initialized');
  }

  @EventPattern('auth.user.registered')
  async handleUserRegistered(@Payload() message: any): Promise<void> {
    // 解析消息格式
    const event: UserRegisteredEvent = message.value || message;
    const eventId = event.eventId || message.eventId;

    if (!eventId) {
      this.logger.warn('Received event without eventId, skipping');
      return;
    }

    const { accountSequence } = event.payload;

    this.logger.debug(
      `Processing user registered event: ${eventId}, accountSequence: ${accountSequence}`,
    );

    // 幂等性检查
    if (await this.isEventProcessed(eventId)) {
      this.logger.debug(`Event ${eventId} already processed, skipping`);
      return;
    }

    try {
      // 为用户创建所有类型的钱包
      await this.userWalletService.createWalletsForUser(accountSequence);

      // 标记为已处理
      await this.markEventProcessed(eventId, event.eventType);

      this.logger.log(
        `Wallets created for user ${accountSequence}, source: ${event.payload.source}`,
      );
    } catch (error) {
      // 如果是重复创建钱包的错误，忽略
      if (
        error instanceof Error &&
        error.message.includes('Unique constraint')
      ) {
        this.logger.debug(
          `Wallets already exist for user ${accountSequence}, marking as processed`,
        );
        await this.markEventProcessed(eventId, event.eventType);
        return;
      }

      this.logger.error(
        `Failed to create wallets for user ${accountSequence}`,
        error instanceof Error ? error.stack : error,
      );
      throw error; // 让 Kafka 重试
    }
  }

  /**
   * 幂等性检查 - Redis + DB 双重检查，4小时去重窗口
   */
  private async isEventProcessed(eventId: string): Promise<boolean> {
    const redisKey = `processed-event:${eventId}`;

    // 1. 先检查 Redis 缓存（快速路径）
    const cached = await this.redis.get(redisKey);
    if (cached) return true;

    // 2. 检查数据库
    const dbRecord = await this.processedEventRepo.findByEventId(eventId);
    if (dbRecord) {
      // 回填 Redis 缓存
      await this.redis.set(redisKey, '1', IDEMPOTENCY_TTL_SECONDS);
      return true;
    }

    return false;
  }

  /**
   * 标记事件为已处理
   */
  private async markEventProcessed(
    eventId: string,
    eventType: string,
  ): Promise<void> {
    // 1. 写入数据库
    await this.processedEventRepo.create({
      eventId,
      eventType,
      sourceService: 'auth-service',
    });

    // 2. 写入 Redis 缓存（4小时 TTL）
    const redisKey = `processed-event:${eventId}`;
    await this.redis.set(redisKey, '1', IDEMPOTENCY_TTL_SECONDS);
  }
}
