/**
 * 转让事件处理器（纯新增）
 * 消费 planting.ownership.removed + planting.ownership.added 事件
 * 更新卖方/买方及其所有上级的团队统计
 *
 * 回滚方式：删除此文件并从 event-handlers/index.ts 和 application.module.ts 中移除引用
 */

import { Injectable, Inject, Logger, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
  IReferralRelationshipRepository,
  REFERRAL_RELATIONSHIP_REPOSITORY,
  ITeamStatisticsRepository,
  TEAM_STATISTICS_REPOSITORY,
} from '../../domain';
import { KafkaService } from '../../infrastructure/messaging/kafka.service';
import { EventAckPublisher } from '../../infrastructure/kafka/event-ack.publisher';
import { PrismaService } from '../../infrastructure/database/prisma.service';

interface PlantingOwnershipRemovedEvent {
  transferOrderNo: string;
  sourceOrderNo: string;
  sellerUserId: string;
  sellerAccountSequence: string;
  treeCount: number;
  contributionPerTree: string;
  selectedProvince: string;
  selectedCity: string;
  originalAdoptionDate: string;
  originalExpireDate: string;
  _outbox?: {
    id: string;
    aggregateId: string;
    eventType: string;
    ackTopic: string;
  };
}

interface PlantingOwnershipAddedEvent {
  transferOrderNo: string;
  sourceOrderNo: string;
  buyerUserId: string;
  buyerAccountSequence: string;
  treeCount: number;
  contributionPerTree: string;
  selectedProvince: string;
  selectedCity: string;
  originalAdoptionDate: string;
  originalExpireDate: string;
  _outbox?: {
    id: string;
    aggregateId: string;
    eventType: string;
    ackTopic: string;
  };
}

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

  constructor(
    private readonly kafkaService: KafkaService,
    private readonly eventAckPublisher: EventAckPublisher,
    private readonly prisma: PrismaService,
    @Inject(REFERRAL_RELATIONSHIP_REPOSITORY)
    private readonly referralRepo: IReferralRelationshipRepository,
    @Inject(TEAM_STATISTICS_REPOSITORY)
    private readonly teamStatsRepo: ITeamStatisticsRepository,
  ) {}

  async onModuleInit() {
    // 订阅卖方减持事件
    await this.kafkaService.subscribe(
      'referral-service-transfer-removed',
      ['planting.ownership.removed'],
      this.handleOwnershipRemoved.bind(this),
    );

    // 订阅买方增持事件
    await this.kafkaService.subscribe(
      'referral-service-transfer-added',
      ['planting.ownership.added'],
      this.handleOwnershipAdded.bind(this),
    );

    this.logger.log('Subscribed to planting.ownership.removed + planting.ownership.added');
  }

  /**
   * 处理卖方减持事件
   * 1. 更新卖方个人认种统计（selfPlantingCount -= treeCount）
   * 2. 更新卖方所有上级的团队认种统计（负数 delta，重新扫描大区）
   */
  private async handleOwnershipRemoved(
    topic: string,
    message: Record<string, unknown>,
  ): Promise<void> {
    const event = message as unknown as PlantingOwnershipRemovedEvent;
    const outboxInfo = event._outbox;
    const eventId = outboxInfo?.aggregateId || event.transferOrderNo;

    this.logger.log(
      `[TRANSFER-REMOVED] Processing: transferOrderNo=${event.transferOrderNo}, ` +
        `seller=${event.sellerAccountSequence}, trees=${event.treeCount}`,
    );

    try {
      // 幂等性检查
      const processedEventId = `removed:${eventId}`;
      const existing = await this.prisma.processedEvent.findUnique({
        where: { eventId: processedEventId },
      });
      if (existing) {
        this.logger.log(`[TRANSFER-REMOVED] Already processed: ${processedEventId}`);
        if (outboxInfo) {
          await this.eventAckPublisher.sendSuccess(eventId, outboxInfo.eventType);
        }
        return;
      }

      // 1. 查找卖方推荐关系
      const relationship = await this.referralRepo.findByAccountSequence(
        event.sellerAccountSequence,
      );
      if (!relationship) {
        this.logger.warn(
          `[TRANSFER-REMOVED] No referral relationship for ${event.sellerAccountSequence}`,
        );
        await this.markProcessedAndAck(processedEventId, 'PlantingOwnershipRemoved', outboxInfo, eventId);
        return;
      }

      const userId = relationship.userId;

      // 2. 更新卖方个人认种统计
      const sellerStats = await this.teamStatsRepo.findByUserId(userId);
      if (sellerStats) {
        sellerStats.removePersonalPlanting(
          event.treeCount,
          event.selectedProvince,
          event.selectedCity,
        );
        await this.teamStatsRepo.save(sellerStats);
        sellerStats.clearDomainEvents();
      }

      // 3. 更新卖方所有上级的团队统计（负数 delta）
      const ancestors = relationship.getAllAncestorIds();
      if (ancestors.length > 0) {
        const updates = ancestors.map((ancestorId, i) => ({
          userId: ancestorId,
          countDelta: -event.treeCount, // 关键：负数
          provinceCode: event.selectedProvince,
          cityCode: event.selectedCity,
          fromDirectReferralId: i === 0 ? userId : ancestors[0],
        }));

        await this.teamStatsRepo.batchUpdateTeamCountsForTransfer(updates);
      }

      // 4. 记录已处理 + 发送 ACK
      await this.markProcessedAndAck(processedEventId, 'PlantingOwnershipRemoved', outboxInfo, eventId);

      this.logger.log(
        `[TRANSFER-REMOVED] ✓ Processed: seller=${event.sellerAccountSequence}, ` +
          `trees=${event.treeCount}, ancestors=${ancestors.length}`,
      );
    } catch (error) {
      this.logger.error(
        `[TRANSFER-REMOVED] ✗ Failed for ${event.transferOrderNo}:`,
        error,
      );
      if (outboxInfo) {
        const msg = error instanceof Error ? error.message : String(error);
        await this.eventAckPublisher.sendFailure(eventId, outboxInfo.eventType, msg);
      }
      throw error;
    }
  }

  /**
   * 处理买方增持事件
   * 1. 更新买方个人认种统计（selfPlantingCount += treeCount）
   * 2. 更新买方所有上级的团队认种统计（正数 delta，复用现有方法）
   * 3. 两方处理完后发布确认事件通知 Saga
   */
  private async handleOwnershipAdded(
    topic: string,
    message: Record<string, unknown>,
  ): Promise<void> {
    const event = message as unknown as PlantingOwnershipAddedEvent;
    const outboxInfo = event._outbox;
    const eventId = outboxInfo?.aggregateId || event.transferOrderNo;

    this.logger.log(
      `[TRANSFER-ADDED] Processing: transferOrderNo=${event.transferOrderNo}, ` +
        `buyer=${event.buyerAccountSequence}, trees=${event.treeCount}`,
    );

    try {
      // 幂等性检查
      const processedEventId = `added:${eventId}`;
      const existing = await this.prisma.processedEvent.findUnique({
        where: { eventId: processedEventId },
      });
      if (existing) {
        this.logger.log(`[TRANSFER-ADDED] Already processed: ${processedEventId}`);
        if (outboxInfo) {
          await this.eventAckPublisher.sendSuccess(eventId, outboxInfo.eventType);
        }
        return;
      }

      // 1. 查找买方推荐关系
      const relationship = await this.referralRepo.findByAccountSequence(
        event.buyerAccountSequence,
      );
      if (!relationship) {
        this.logger.warn(
          `[TRANSFER-ADDED] No referral relationship for ${event.buyerAccountSequence}`,
        );
        await this.markProcessedAndAck(processedEventId, 'PlantingOwnershipAdded', outboxInfo, eventId);
        return;
      }

      const userId = relationship.userId;

      // 2. 更新买方个人认种统计
      const buyerStats = await this.teamStatsRepo.findByUserId(userId);
      if (buyerStats) {
        buyerStats.addPersonalPlanting(
          event.treeCount,
          event.selectedProvince,
          event.selectedCity,
        );
        await this.teamStatsRepo.save(buyerStats);
        buyerStats.clearDomainEvents();
      }

      // 3. 更新买方所有上级的团队统计（正数 delta，复用现有方法）
      const ancestors = relationship.getAllAncestorIds();
      if (ancestors.length > 0) {
        const updates = ancestors.map((ancestorId, i) => ({
          userId: ancestorId,
          countDelta: event.treeCount, // 正数
          provinceCode: event.selectedProvince,
          cityCode: event.selectedCity,
          fromDirectReferralId: i === 0 ? userId : ancestors[0],
        }));

        await this.teamStatsRepo.batchUpdateTeamCounts(updates);
      }

      // 4. 记录已处理 + 发送 ACK
      await this.markProcessedAndAck(processedEventId, 'PlantingOwnershipAdded', outboxInfo, eventId);

      // 5. 两方都处理完后，发布确认事件通知 transfer-service Saga 推进
      await this.publishTransferStatsUpdated(event.transferOrderNo);

      this.logger.log(
        `[TRANSFER-ADDED] ✓ Processed: buyer=${event.buyerAccountSequence}, ` +
          `trees=${event.treeCount}, ancestors=${ancestors.length}`,
      );
    } catch (error) {
      this.logger.error(
        `[TRANSFER-ADDED] ✗ Failed for ${event.transferOrderNo}:`,
        error,
      );
      if (outboxInfo) {
        const msg = error instanceof Error ? error.message : String(error);
        await this.eventAckPublisher.sendFailure(eventId, outboxInfo.eventType, msg);
      }
      throw error;
    }
  }

  /**
   * 发布团队统计更新完成确认（通知 Saga）
   */
  private async publishTransferStatsUpdated(transferOrderNo: string): Promise<void> {
    await this.kafkaService.publish({
      topic: 'referral.transfer.stats-updated',
      key: transferOrderNo,
      value: {
        transferOrderNo,
        consumerService: 'referral-service',
        success: true,
        confirmedAt: new Date().toISOString(),
      },
    });

    this.logger.log(
      `[TRANSFER] Published referral.transfer.stats-updated for ${transferOrderNo}`,
    );
  }

  /**
   * 标记事件已处理并发送 ACK
   */
  private async markProcessedAndAck(
    processedEventId: string,
    eventType: string,
    outboxInfo: PlantingOwnershipRemovedEvent['_outbox'],
    eventId: string,
  ): Promise<void> {
    await this.prisma.processedEvent.create({
      data: { eventId: processedEventId, eventType },
    });

    if (outboxInfo) {
      await this.eventAckPublisher.sendSuccess(eventId, outboxInfo.eventType);
    }
  }
}
