/**
 * 转让执行处理器（纯新增）
 * 消费 transfer.ownership.execute 事件
 * 执行所有权变更：卖方减持 → 买方增持 → 发布 Outbox 事件
 *
 * 回滚方式：删除此文件并从 infrastructure.module.ts 中移除引用
 */

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

interface TransferExecutePayload {
  transferOrderNo: string;
  sellerUserId: string;
  sellerAccountSequence: string;
  buyerUserId: string;
  buyerAccountSequence: string;
  sourceOrderNo: string;
  treeCount: number;
  contributionPerTree: string;
  selectedProvince: string;
  selectedCity: string;
  originalAdoptionDate: string;
  originalExpireDate: string;
}

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

  constructor(private readonly prisma: PrismaService) {}

  @EventPattern('transfer.ownership.execute')
  async handle(
    @Payload() message: TransferExecutePayload,
    @Ctx() context: KafkaContext,
  ): Promise<void> {
    const {
      transferOrderNo,
      sellerUserId,
      sellerAccountSequence,
      buyerUserId,
      buyerAccountSequence,
      sourceOrderNo,
      treeCount,
      contributionPerTree,
      selectedProvince,
      selectedCity,
      originalAdoptionDate,
      originalExpireDate,
    } = message;

    this.logger.log(
      `[TRANSFER-EXECUTE] Received execute request: ${transferOrderNo}, ` +
        `seller=${sellerUserId} → buyer=${buyerUserId}, trees=${treeCount}`,
    );

    try {
      // 幂等性检查：如果已经转让完成，跳过
      const existing = await this.prisma.plantingTransferRecord.findUnique({
        where: { transferOrderNo },
      });

      if (existing && existing.status === 'TRANSFERRED') {
        this.logger.log(
          `[TRANSFER-EXECUTE] Already transferred: ${transferOrderNo}`,
        );
        return;
      }

      if (!existing || existing.status !== 'LOCKED') {
        this.logger.error(
          `[TRANSFER-EXECUTE] Invalid state: ${transferOrderNo}, status=${existing?.status}`,
        );
        return;
      }

      const now = new Date();
      const sellerUserIdBigInt = BigInt(sellerUserId);
      const buyerUserIdBigInt = BigInt(buyerUserId);

      // 事务：所有权变更 + Outbox 事件
      await this.prisma.executeTransaction(async (tx) => {
        // 1. 更新 PlantingTransferRecord → TRANSFERRED
        await tx.plantingTransferRecord.update({
          where: { transferOrderNo },
          data: {
            toUserId: buyerUserIdBigInt,
            toAccountSequence: buyerAccountSequence,
            contributionPerTree: new Prisma.Decimal(contributionPerTree),
            status: 'TRANSFERRED',
            transferredAt: now,
          },
        });

        // 2. 更新 PlantingOrder.transferLockedCount（锁定已消费）
        await tx.plantingOrder.update({
          where: { id: existing.sourceOrderId },
          data: {
            transferLockedCount: { decrement: treeCount },
          },
        });

        // 3. 更新卖方 PlantingPosition（减持）
        await tx.plantingPosition.update({
          where: { userId: sellerUserIdBigInt },
          data: {
            effectiveTreeCount: { decrement: treeCount },
            totalTreeCount: { decrement: treeCount },
          },
        });

        // 4. 更新卖方 PositionDistribution（减持）
        await tx.positionDistribution.update({
          where: {
            userId_provinceCode_cityCode: {
              userId: sellerUserIdBigInt,
              provinceCode: selectedProvince,
              cityCode: selectedCity,
            },
          },
          data: {
            treeCount: { decrement: treeCount },
          },
        });

        // 5. Upsert 买方 PlantingPosition（增持）
        await tx.plantingPosition.upsert({
          where: { userId: buyerUserIdBigInt },
          create: {
            userId: buyerUserIdBigInt,
            effectiveTreeCount: treeCount,
            totalTreeCount: treeCount,
            pendingTreeCount: 0,
          },
          update: {
            effectiveTreeCount: { increment: treeCount },
            totalTreeCount: { increment: treeCount },
          },
        });

        // 6. Upsert 买方 PositionDistribution（增持）
        await tx.positionDistribution.upsert({
          where: {
            userId_provinceCode_cityCode: {
              userId: buyerUserIdBigInt,
              provinceCode: selectedProvince,
              cityCode: selectedCity,
            },
          },
          create: {
            userId: buyerUserIdBigInt,
            provinceCode: selectedProvince,
            cityCode: selectedCity,
            treeCount: treeCount,
          },
          update: {
            treeCount: { increment: treeCount },
          },
        });

        // 7. 创建 3 个 Outbox 事件（B 方案，由 OutboxPublisherService 轮询发布）
        const commonPayload = {
          transferOrderNo,
          sourceOrderNo,
          sourceOrderId: existing.sourceOrderId.toString(), // bigint → string，供 contribution-service 查找原始认种记录
          treeCount,
          contributionPerTree,
          selectedProvince,
          selectedCity,
          originalAdoptionDate,
          originalExpireDate,
        };

        await tx.outboxEvent.createMany({
          data: [
            // 事件 1：通知 transfer-service 所有权变更完成
            {
              eventType: 'PlantingTransferCompleted',
              topic: 'planting.transfer.completed',
              key: transferOrderNo,
              payload: {
                ...commonPayload,
                sellerUserId,
                sellerAccountSequence,
                buyerUserId,
                buyerAccountSequence,
                status: 'TRANSFERRED',
                transferredAt: now.toISOString(),
              } as unknown as Prisma.JsonObject,
              aggregateId: transferOrderNo,
              aggregateType: 'PlantingTransfer',
              status: 'PENDING',
            },
            // 事件 2：通知 contribution + referral 卖方减持
            {
              eventType: 'PlantingOwnershipRemoved',
              topic: 'planting.ownership.removed',
              key: sellerUserId,
              payload: {
                ...commonPayload,
                sellerUserId,
                sellerAccountSequence,
              } as unknown as Prisma.JsonObject,
              aggregateId: transferOrderNo,
              aggregateType: 'PlantingTransfer',
              status: 'PENDING',
            },
            // 事件 3：通知 contribution + referral 买方增持
            {
              eventType: 'PlantingOwnershipAdded',
              topic: 'planting.ownership.added',
              key: buyerUserId,
              payload: {
                ...commonPayload,
                buyerUserId,
                buyerAccountSequence,
              } as unknown as Prisma.JsonObject,
              aggregateId: transferOrderNo,
              aggregateType: 'PlantingTransfer',
              status: 'PENDING',
            },
          ],
        });
      });

      this.logger.log(
        `[TRANSFER-EXECUTE] ✓ Ownership transferred: ${transferOrderNo}, ` +
          `seller=${sellerUserId} → buyer=${buyerUserId}, ${treeCount} trees`,
      );
    } catch (error) {
      this.logger.error(
        `[TRANSFER-EXECUTE] ✗ Failed to execute transfer ${transferOrderNo}:`,
        error,
      );
      // 不抛出异常 - 消息会被 Kafka 重新投递（通过 transfer-service Saga 重试机制）
    }
  }
}
