import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { ContributionSyncService } from '../services/contribution-sync.service';
import { NetworkSyncService } from '../services/network-sync.service';
import { Kafka, Consumer, EachMessagePayload } from 'kafkajs';

@Injectable()
export class ContributionEventHandler implements OnModuleInit {
  private readonly logger = new Logger(ContributionEventHandler.name);
  private consumer: Consumer;

  constructor(
    private readonly syncService: ContributionSyncService,
    private readonly networkSyncService: NetworkSyncService,
    private readonly configService: ConfigService,
  ) {}

  async onModuleInit() {
    const kafkaBrokers = this.configService.get<string>('KAFKA_BROKERS', 'localhost:9092');

    // contribution-service 使用 Outbox Pattern 直接发送 Kafka 消息到这些 topic
    // topic 名称格式: contribution.{eventType.toLowerCase()}
    const topics = [
      'contribution.contributionaccountupdated',
      'contribution.dailysnapshotcreated',
      'contribution.systemaccountsynced',
      'contribution.networkprogressupdated',
      'contribution.unallocatedcontributionsynced',
    ];

    const kafka = new Kafka({
      clientId: 'mining-service',
      brokers: kafkaBrokers.split(','),
    });

    this.consumer = kafka.consumer({ groupId: 'mining-service-contribution-sync' });

    try {
      await this.consumer.connect();

      // 订阅多个 topic
      for (const topic of topics) {
        await this.consumer.subscribe({ topic, fromBeginning: false });
      }

      await this.consumer.run({
        eachMessage: async (payload: EachMessagePayload) => {
          await this.handleMessage(payload);
        },
      });

      this.logger.log(`Subscribed to ${topics.length} topics for contribution sync: ${topics.join(', ')}`);
    } catch (error) {
      this.logger.error('Failed to connect to Kafka for contribution sync', error);
    }
  }

  private async handleMessage(payload: EachMessagePayload): Promise<void> {
    try {
      const { message, topic } = payload;
      if (!message.value) return;

      const event = JSON.parse(message.value.toString());

      // Outbox Pattern 直接发送的消息格式：payload 本身就是事件数据
      // 可以通过 topic 或 eventType 字段判断事件类型
      const eventPayload = event.eventType ? event : (event.payload || event);
      const eventType = eventPayload.eventType || this.extractEventTypeFromTopic(topic);

      if (!eventPayload) return;

      if (eventType === 'ContributionAccountUpdated') {
        this.logger.debug(`Received ContributionAccountUpdated for ${eventPayload.accountSequence}`);

        // 使用 effectiveContribution 作为挖矿算力
        await this.syncService.handleContributionCalculated({
          accountSequence: eventPayload.accountSequence,
          personalContribution: eventPayload.effectiveContribution || eventPayload.totalContribution || '0',
          calculatedAt: eventPayload.createdAt || new Date().toISOString(),
        });
      } else if (eventType === 'DailySnapshotCreated') {
        this.logger.log(`Received DailySnapshotCreated for ${eventPayload.snapshotDate}`);

        await this.syncService.handleDailySnapshotCreated({
          snapshotId: eventPayload.snapshotId || eventPayload.snapshotDate || 'unknown',
          snapshotDate: eventPayload.snapshotDate,
          totalContribution: eventPayload.totalContribution || eventPayload.networkTotalContribution || '0',
          activeAccounts: eventPayload.activeAccounts || eventPayload.accountCount || 0,
        });
      } else if (eventType === 'SystemAccountSynced') {
        this.logger.log(
          `Received SystemAccountSynced for ${eventPayload.accountType} (regionCode=${eventPayload.regionCode})`,
        );

        await this.networkSyncService.handleSystemAccountSynced({
          accountType: eventPayload.accountType,
          regionCode: eventPayload.regionCode || null,
          name: eventPayload.name,
          contributionBalance: eventPayload.contributionBalance,
        });
      } else if (eventType === 'NetworkProgressUpdated') {
        this.logger.log(`Received NetworkProgressUpdated: trees=${eventPayload.totalTreeCount}`);

        await this.networkSyncService.handleNetworkProgressUpdated({
          totalTreeCount: eventPayload.totalTreeCount,
          totalAdoptionOrders: eventPayload.totalAdoptionOrders,
          totalAdoptedUsers: eventPayload.totalAdoptedUsers,
          currentUnit: eventPayload.currentUnit,
          currentMultiplier: eventPayload.currentMultiplier,
          currentContributionPerTree: eventPayload.currentContributionPerTree,
          nextUnitTreeCount: eventPayload.nextUnitTreeCount,
        });
      } else if (eventType === 'UnallocatedContributionSynced') {
        this.logger.log(`Received UnallocatedContributionSynced: adoption=${eventPayload.sourceAdoptionId}, type=${eventPayload.contributionType}`);

        await this.networkSyncService.handleUnallocatedContributionSynced({
          sourceAdoptionId: eventPayload.sourceAdoptionId,
          sourceAccountSequence: eventPayload.sourceAccountSequence,
          wouldBeAccountSequence: eventPayload.wouldBeAccountSequence,
          contributionType: eventPayload.contributionType,
          amount: eventPayload.amount,
          reason: eventPayload.reason,
          effectiveDate: eventPayload.effectiveDate,
          expireDate: eventPayload.expireDate,
        });
      }
    } catch (error) {
      this.logger.error('Failed to handle contribution event', error);
    }
  }

  /**
   * 从 topic 名称提取事件类型
   * 例如: contribution.unallocatedcontributionsynced -> UnallocatedContributionSynced
   */
  private extractEventTypeFromTopic(topic: string): string {
    // topic 格式: contribution.{eventtype}
    const parts = topic.split('.');
    if (parts.length < 2) return '';

    const rawType = parts[1]; // e.g., unallocatedcontributionsynced

    // 已知的事件类型映射
    const typeMap: Record<string, string> = {
      contributionaccountupdated: 'ContributionAccountUpdated',
      dailysnapshotcreated: 'DailySnapshotCreated',
      systemaccountsynced: 'SystemAccountSynced',
      networkprogressupdated: 'NetworkProgressUpdated',
      unallocatedcontributionsynced: 'UnallocatedContributionSynced',
    };

    return typeMap[rawType] || rawType;
  }
}
