import { Injectable, Logger, Inject } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { ContractSigningService } from '../services/contract-signing.service';
import {
  IPlantingOrderRepository,
  PLANTING_ORDER_REPOSITORY,
} from '../../domain/repositories';
import { IdentityServiceClient } from '../../infrastructure/external/identity-service.client';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';

/**
 * 合同签署恢复定时任务
 *
 * 每3分钟扫描一次已支付但未创建合同的订单
 * 为已通过KYC的用户补创建合同签署任务
 *
 * 场景：
 * 1. KYCVerified 事件发布失败或消费失败
 * 2. identity-service 接口临时不可用
 * 3. 其他导致合同任务未创建的异常情况
 */
@Injectable()
export class ContractSigningRecoveryJob {
  private readonly logger = new Logger(ContractSigningRecoveryJob.name);

  constructor(
    private readonly contractSigningService: ContractSigningService,
    @Inject(PLANTING_ORDER_REPOSITORY)
    private readonly orderRepo: IPlantingOrderRepository,
    private readonly identityServiceClient: IdentityServiceClient,
    private readonly prisma: PrismaService,
  ) {}

  /**
   * 每3分钟执行一次
   */
  @Cron('0 */3 * * * *')
  async handleRecovery(): Promise<void> {
    this.logger.debug('[CONTRACT-RECOVERY] Starting recovery check...');

    try {
      // 1. 查找所有已支付但未创建合同的订单
      const ordersWithoutContract = await this.findAllOrdersWithoutContract();

      if (ordersWithoutContract.length === 0) {
        this.logger.debug('[CONTRACT-RECOVERY] No orders need recovery');
        return;
      }

      this.logger.log(
        `[CONTRACT-RECOVERY] Found ${ordersWithoutContract.length} orders without contract`,
      );

      let successCount = 0;
      let skipCount = 0;
      let errorCount = 0;

      // 2. 逐个处理订单 - 订单中已包含 accountSequence
      for (const order of ordersWithoutContract) {
        try {
          // 检查省市信息
          if (!order.selectedProvince || !order.selectedCity) {
            this.logger.warn(
              `[CONTRACT-RECOVERY] Order ${order.orderNo} has no province/city, skipping`,
            );
            skipCount++;
            continue;
          }

          // 订单中已包含 accountSequence
          const accountSequence = order.accountSequence;

          // 使用 accountSequence 获取 KYC 信息
          const kycInfo = await this.identityServiceClient.getUserKycInfo(accountSequence);

          if (!kycInfo) {
            this.logger.debug(
              `[CONTRACT-RECOVERY] User ${accountSequence} KYC not verified, skipping order ${order.orderNo}`,
            );
            skipCount++;
            continue;
          }

          // 创建合同签署任务
          await this.contractSigningService.createSigningTask({
            orderNo: order.orderNo,
            userId: order.userId,
            accountSequence,
            treeCount: order.treeCount,
            totalAmount: Number(order.totalAmount),
            provinceCode: order.selectedProvince,
            provinceName: order.selectedProvince,
            cityCode: order.selectedCity,
            cityName: order.selectedCity,
            userPhoneNumber: kycInfo.phoneNumber,
            userRealName: kycInfo.realName,
            userIdCardNumber: kycInfo.idCardNumber,
          });

          successCount++;
          this.logger.log(`[CONTRACT-RECOVERY] Created contract for order: ${order.orderNo}`);
        } catch (orderError) {
          // createSigningTask 有幂等检查，重复创建会直接返回已存在的任务
          // 如果是其他错误才记录
          const errorMessage = orderError instanceof Error ? orderError.message : String(orderError);
          if (!errorMessage.includes('already exists')) {
            errorCount++;
            this.logger.error(
              `[CONTRACT-RECOVERY] Failed to create contract for order ${order.orderNo}:`,
              orderError,
            );
          }
        }
      }

      this.logger.log(
        `[CONTRACT-RECOVERY] Completed: success=${successCount}, skipped=${skipCount}, errors=${errorCount}`,
      );
    } catch (error) {
      this.logger.error('[CONTRACT-RECOVERY] Error in recovery job:', error);
    }
  }

  /**
   * 查找所有已支付但未创建合同的订单
   */
  private async findAllOrdersWithoutContract() {
    const paidStatuses = ['PAID', 'FUND_ALLOCATED', 'POOL_SCHEDULED', 'POOL_INJECTED', 'MINING_ENABLED'];

    // 获取已有合同的订单号
    const existingContracts = await this.prisma.contractSigningTask.findMany({
      select: { orderNo: true },
    });
    const existingOrderNos = new Set(existingContracts.map((c) => c.orderNo));

    // 查找没有合同的订单
    const orders = await this.prisma.plantingOrder.findMany({
      where: {
        status: { in: paidStatuses },
      },
      orderBy: { createdAt: 'asc' },
    });

    // 过滤掉已有合同的订单
    return orders.filter((o) => !existingOrderNos.has(o.orderNo));
  }
}
