import { Injectable, Logger } from '@nestjs/common';
import Decimal from 'decimal.js';
import { CDCEvent } from '../../infrastructure/kafka/cdc-consumer.service';
import { SyncedDataRepository } from '../../infrastructure/persistence/repositories/synced-data.repository';
import { ContributionCalculationService } from '../services/contribution-calculation.service';
import { UnitOfWork } from '../../infrastructure/persistence/unit-of-work/unit-of-work';

/**
 * 认种 CDC 事件处理器
 * 处理从种植服务同步过来的认种数据
 * 认种是触发算力计算的核心事件
 */
@Injectable()
export class AdoptionSyncedHandler {
  private readonly logger = new Logger(AdoptionSyncedHandler.name);

  constructor(
    private readonly syncedDataRepository: SyncedDataRepository,
    private readonly contributionCalculationService: ContributionCalculationService,
    private readonly unitOfWork: UnitOfWork,
  ) {}

  async handle(event: CDCEvent): Promise<void> {
    const { op, before, after } = event.payload;

    try {
      switch (op) {
        case 'c': // create
        case 'r': // read (snapshot)
          await this.handleCreate(after, event.sequenceNum);
          break;
        case 'u': // update
          await this.handleUpdate(after, before, event.sequenceNum);
          break;
        case 'd': // delete
          await this.handleDelete(before);
          break;
        default:
          this.logger.warn(`Unknown CDC operation: ${op}`);
      }
    } catch (error) {
      this.logger.error(`Failed to handle adoption CDC event`, error);
      throw error;
    }
  }

  private async handleCreate(data: any, sequenceNum: bigint): Promise<void> {
    if (!data) return;

    await this.unitOfWork.executeInTransaction(async () => {
      // 保存同步的认种数据
      const adoption = await this.syncedDataRepository.upsertSyncedAdoption({
        originalAdoptionId: BigInt(data.id),
        accountSequence: data.account_sequence || data.accountSequence,
        treeCount: data.tree_count || data.treeCount,
        adoptionDate: new Date(data.adoption_date || data.adoptionDate || data.created_at || data.createdAt),
        status: data.status ?? null,
        contributionPerTree: new Decimal(data.contribution_per_tree || data.contributionPerTree || '1'),
        sourceSequenceNum: sequenceNum,
      });

      // 触发算力计算
      await this.contributionCalculationService.calculateForAdoption(adoption.originalAdoptionId);
    });

    this.logger.log(
      `Adoption synced and contribution calculated: ${data.id}, account: ${data.account_sequence || data.accountSequence}`,
    );
  }

  private async handleUpdate(after: any, before: any, sequenceNum: bigint): Promise<void> {
    if (!after) return;

    const originalAdoptionId = BigInt(after.id);

    // 检查是否已经处理过
    const existingAdoption = await this.syncedDataRepository.findSyncedAdoptionByOriginalId(originalAdoptionId);

    if (existingAdoption?.contributionDistributed) {
      // 如果树数量发生变化，需要重新计算（这种情况较少）
      const newTreeCount = after.tree_count || after.treeCount;
      if (existingAdoption.treeCount !== newTreeCount) {
        this.logger.warn(
          `Adoption tree count changed after processing: ${originalAdoptionId}. This requires special handling.`,
        );
        // TODO: 实现树数量变化的处理逻辑
      }
      return;
    }

    await this.unitOfWork.executeInTransaction(async () => {
      const adoption = await this.syncedDataRepository.upsertSyncedAdoption({
        originalAdoptionId: originalAdoptionId,
        accountSequence: after.account_sequence || after.accountSequence,
        treeCount: after.tree_count || after.treeCount,
        adoptionDate: new Date(after.adoption_date || after.adoptionDate || after.created_at || after.createdAt),
        status: after.status ?? null,
        contributionPerTree: new Decimal(after.contribution_per_tree || after.contributionPerTree || '1'),
        sourceSequenceNum: sequenceNum,
      });

      if (!existingAdoption?.contributionDistributed) {
        await this.contributionCalculationService.calculateForAdoption(adoption.originalAdoptionId);
      }
    });

    this.logger.debug(`Adoption updated: ${originalAdoptionId}`);
  }

  private async handleDelete(data: any): Promise<void> {
    if (!data) return;
    // 认种删除需要特殊处理（回滚算力）
    // 但通常不会发生删除操作
    this.logger.warn(`Adoption delete event received: ${data.id}. This may require contribution rollback.`);
  }
}
