/**
 * 转让锁定处理器（纯新增）
 * 消费 transfer.trees.lock 事件
 * 锁定卖方指定订单的树，防止重复转让
 *
 * 回滚方式：删除此文件并从 infrastructure.module.ts 中移除引用
 */

import { Controller, Logger, Inject } from '@nestjs/common';
import { EventPattern, Payload, Ctx, KafkaContext } from '@nestjs/microservices';
import { ClientKafka } from '@nestjs/microservices';
import { PrismaService } from '../persistence/prisma/prisma.service';

interface TransferLockPayload {
  transferOrderNo: string;
  sellerUserId: string;
  sourceOrderNo: string;
  treeCount: number;
  sellerAccountSequence: string;
}

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

  constructor(
    private readonly prisma: PrismaService,
    @Inject('KAFKA_SERVICE')
    private readonly kafkaClient: ClientKafka,
  ) {}

  @EventPattern('transfer.trees.lock')
  async handle(
    @Payload() message: TransferLockPayload,
    @Ctx() context: KafkaContext,
  ): Promise<void> {
    const {
      transferOrderNo,
      sellerUserId,
      sourceOrderNo,
      treeCount,
      sellerAccountSequence,
    } = message;

    this.logger.log(
      `[TRANSFER-LOCK] Received lock request: ${transferOrderNo}, orderNo=${sourceOrderNo}, trees=${treeCount}`,
    );

    try {
      // 幂等性检查：如果已经锁定，直接返回成功
      const existing = await this.prisma.plantingTransferRecord.findUnique({
        where: { transferOrderNo },
      });

      if (existing) {
        this.logger.log(
          `[TRANSFER-LOCK] Already locked: ${transferOrderNo}, status=${existing.status}`,
        );
        this.publishAck(transferOrderNo, true);
        return;
      }

      // 验证订单存在且属于卖方
      const order = await this.prisma.plantingOrder.findUnique({
        where: { orderNo: sourceOrderNo },
      });

      if (!order) {
        this.logger.error(`[TRANSFER-LOCK] Order not found: ${sourceOrderNo}`);
        this.publishAck(transferOrderNo, false, '认种订单不存在');
        return;
      }

      if (order.userId !== BigInt(sellerUserId)) {
        this.logger.error(
          `[TRANSFER-LOCK] Order ${sourceOrderNo} does not belong to seller ${sellerUserId}`,
        );
        this.publishAck(transferOrderNo, false, '订单不属于卖方');
        return;
      }

      if (order.status !== 'MINING_ENABLED') {
        this.logger.error(
          `[TRANSFER-LOCK] Order ${sourceOrderNo} status is ${order.status}, not MINING_ENABLED`,
        );
        this.publishAck(transferOrderNo, false, '订单状态不允许转让');
        return;
      }

      // 计算可转让棵数
      const transferredAgg = await this.prisma.plantingTransferRecord.aggregate({
        where: { sourceOrderNo, status: 'TRANSFERRED' },
        _sum: { treeCount: true },
      });
      const transferredCount = transferredAgg._sum.treeCount || 0;
      const available =
        order.treeCount - (order.transferLockedCount || 0) - transferredCount;

      if (available < treeCount) {
        this.logger.error(
          `[TRANSFER-LOCK] Insufficient trees: available=${available}, requested=${treeCount}`,
        );
        this.publishAck(
          transferOrderNo,
          false,
          `可转让棵数不足，可用${available}棵`,
        );
        return;
      }

      // 计算算力值和日期
      const contributionPerTree = order.totalAmount.div(order.treeCount);
      const adoptionDate = order.paidAt || order.miningEnabledAt || order.createdAt;
      const expireDate = new Date(adoptionDate);
      expireDate.setFullYear(expireDate.getFullYear() + 5);

      // 事务：创建锁定记录 + 更新锁定计数
      await this.prisma.executeTransaction(async (tx) => {
        await tx.plantingTransferRecord.create({
          data: {
            transferOrderNo,
            sourceOrderNo,
            sourceOrderId: order.id,
            fromUserId: BigInt(sellerUserId),
            fromAccountSequence: sellerAccountSequence,
            treeCount,
            selectedProvince: order.selectedProvince || '',
            selectedCity: order.selectedCity || '',
            contributionPerTree,
            originalAdoptionDate: adoptionDate,
            originalExpireDate: expireDate,
            status: 'LOCKED',
            lockedAt: new Date(),
          },
        });

        await tx.plantingOrder.update({
          where: { id: order.id },
          data: {
            transferLockedCount: { increment: treeCount },
          },
        });
      });

      this.logger.log(
        `[TRANSFER-LOCK] ✓ Trees locked: ${transferOrderNo}, ${treeCount} trees from order ${sourceOrderNo}`,
      );

      this.publishAck(transferOrderNo, true);
    } catch (error) {
      this.logger.error(
        `[TRANSFER-LOCK] ✗ Failed to lock trees for ${transferOrderNo}:`,
        error,
      );
      this.publishAck(
        transferOrderNo,
        false,
        `锁定失败: ${(error as Error).message}`,
      );
    }
  }

  private publishAck(
    transferOrderNo: string,
    success: boolean,
    error?: string,
  ): void {
    const message = {
      key: transferOrderNo,
      value: JSON.stringify({
        transferOrderNo,
        success,
        error,
        confirmedAt: new Date().toISOString(),
      }),
    };

    this.kafkaClient.emit('transfer.trees.lock.ack', message);
    this.logger.log(
      `[TRANSFER-LOCK] ACK sent: ${transferOrderNo}, success=${success}`,
    );
  }
}
