import { Injectable, Logger, BadRequestException, NotFoundException, ForbiddenException } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import { C2cOrderRepository, C2cOrderEntity } from '../../infrastructure/persistence/repositories/c2c-order.repository';
import { TradingAccountRepository } from '../../infrastructure/persistence/repositories/trading-account.repository';
import { RedisService } from '../../infrastructure/redis/redis.service';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { IdentityClient } from '../../infrastructure/identity/identity.client';
import { Money } from '../../domain/value-objects/money.vo';
import { TradingAccountAggregate } from '../../domain/aggregates/trading-account.aggregate';
import Decimal from 'decimal.js';

// C2C 订单类型常量
const C2C_ORDER_TYPE = {
  BUY: 'BUY',
  SELL: 'SELL',
} as const;

// C2C 订单状态常量
const C2C_ORDER_STATUS = {
  PENDING: 'PENDING',
  MATCHED: 'MATCHED',
  PAID: 'PAID',
  COMPLETED: 'COMPLETED',
  CANCELLED: 'CANCELLED',
  EXPIRED: 'EXPIRED',
} as const;

// C2C 收款方式常量
const C2C_PAYMENT_METHOD = {
  GREEN_POINTS: 'GREEN_POINTS',
  ALIPAY: 'ALIPAY',
  WECHAT: 'WECHAT',
  BANK: 'BANK',
} as const;

// 默认超时时间配置（分钟）
const DEFAULT_PAYMENT_TIMEOUT_MINUTES = 15;
const DEFAULT_CONFIRM_TIMEOUT_MINUTES = 60;
// PENDING 挂单超时时间（小时）- 超过此时间未被接单的广告自动取消并解冻资产
const DEFAULT_PENDING_TIMEOUT_HOURS = 24;

/**
 * C2C 场外交易服务
 *
 * 业务流程（C2C交易的是积分值，支付方式是绿积分/外部1.0系统）：
 * 1. 用户发布广告（createOrder）-> 状态: PENDING
 *    - BUY 类型: 验证积分值余额，不冻结（买方通过外部支付绿积分）
 *    - SELL 类型: 冻结卖方的积分值（cashBalance）
 * 2. 其他用户接单（takeOrder）-> 状态: MATCHED
 *    - 接BUY单（taker=卖方）: 冻结taker的积分值
 *    - 接SELL单（taker=买方）: 不冻结（买方通过外部支付绿积分）
 * 3. 买方付款后点击确认付款（confirmPayment）-> 状态: PAID
 * 4. 卖方确认收款（confirmReceived）-> 状态: COMPLETED
 *    - 解冻卖方积分值并划转给买方
 */
@Injectable()
export class C2cService {
  private readonly logger = new Logger(C2cService.name);

  constructor(
    private readonly c2cOrderRepository: C2cOrderRepository,
    private readonly tradingAccountRepository: TradingAccountRepository,
    private readonly redis: RedisService,
    private readonly prisma: PrismaService,
    private readonly identityClient: IdentityClient,
  ) {}

  /**
   * 生成C2C订单号
   */
  private generateOrderNo(): string {
    const now = new Date();
    const dateStr = now.toISOString().slice(0, 10).replace(/-/g, '');
    const timeStr = now.toISOString().slice(11, 19).replace(/:/g, '');
    const random = Math.random().toString(36).substring(2, 8).toUpperCase();
    return `C2C${dateStr}${timeStr}${random}`;
  }

  /**
   * 创建C2C订单（发布广告）
   */
  async createOrder(
    accountSequence: string,
    type: 'BUY' | 'SELL',
    price: string,
    quantity: string,
    options?: {
      minAmount?: string;
      maxAmount?: string;
      // 收款信息（卖单必填）
      paymentMethod?: string;
      paymentAccount?: string;
      paymentQrCode?: string;
      paymentRealName?: string;
      remark?: string;
      userId?: string;
      phone?: string;
      nickname?: string;
    },
  ): Promise<C2cOrderEntity> {
    const lockKey = `c2c:create:${accountSequence}`;
    const lockValue = await this.redis.acquireLock(lockKey, 30);
    if (!lockValue) {
      throw new BadRequestException('操作太频繁，请稍后再试');
    }

    try {
      const priceDecimal = new Decimal(price);
      const quantityDecimal = new Decimal(quantity);

      if (priceDecimal.lte(0)) {
        throw new BadRequestException('价格必须大于0');
      }
      if (quantityDecimal.lte(0)) {
        throw new BadRequestException('数量必须大于0');
      }
      // #11: 价格必须为1（1:1），数量最小为1
      if (!priceDecimal.equals(1)) {
        throw new BadRequestException('C2C交易价格固定为1:1');
      }
      if (quantityDecimal.lt(1)) {
        throw new BadRequestException('最小交易数量为1');
      }

      // 卖单：自动获取卖家 Kava 地址（用于绿积分转账）
      let sellerKavaAddress: string | null = null;
      if (type === C2C_ORDER_TYPE.SELL) {
        sellerKavaAddress = await this.identityClient.getUserKavaAddress(accountSequence);
        if (!sellerKavaAddress) {
          throw new BadRequestException('未找到您的 Kava 钱包地址，请先绑定钱包');
        }
      }

      // 计算总金额
      const totalAmount = priceDecimal.mul(quantityDecimal);

      // 获取用户交易账户，不存在则自动创建零余额账户
      let account = await this.tradingAccountRepository.findByAccountSequence(accountSequence);
      if (!account) {
        this.logger.log(`C2C: 用户 ${accountSequence} 无交易账户，自动创建`);
        const newAccount = TradingAccountAggregate.create(accountSequence);
        await this.tradingAccountRepository.save(newAccount);
        account = await this.tradingAccountRepository.findByAccountSequence(accountSequence);
        if (!account) {
          throw new NotFoundException('交易账户创建失败');
        }
      }

      // 检查余额并冻结资产
      if (type === C2C_ORDER_TYPE.BUY) {
        // 买入订单：买方通过外部系统支付绿积分，不需要验证积分值余额也不冻结
      } else {
        // 卖出订单：需要冻结积分值（C2C交易的是积分值）
        const quantityMoney = new Money(quantityDecimal);
        if (account.availableCash.isLessThan(quantityMoney)) {
          throw new BadRequestException(`积分值余额不足，需要 ${quantity}，可用 ${account.availableCash.toString()}`);
        }
        // 冻结积分值
        await this.tradingAccountRepository.freezeCash(accountSequence, quantityDecimal);
      }

      // 创建订单
      const orderNo = this.generateOrderNo();
      const order = await this.c2cOrderRepository.create({
        orderNo,
        type: type as any,
        makerAccountSequence: accountSequence,
        makerUserId: options?.userId,
        makerPhone: options?.phone,
        makerNickname: options?.nickname,
        price: priceDecimal.toString(),
        quantity: quantityDecimal.toString(),
        totalAmount: totalAmount.toString(),
        minAmount: options?.minAmount,
        maxAmount: options?.maxAmount,
        // 收款信息（卖单时填写）
        paymentMethod: options?.paymentMethod,
        paymentAccount: options?.paymentAccount,
        paymentQrCode: options?.paymentQrCode,
        paymentRealName: options?.paymentRealName,
        // 卖家 Kava 地址（卖单时自动获取）
        sellerKavaAddress,
        remark: options?.remark,
      });

      this.logger.log(`C2C订单创建成功: ${orderNo}, 类型: ${type}, 数量: ${quantity}, 价格: ${price}`);
      return order;
    } finally {
      await this.redis.releaseLock(lockKey, lockValue);
    }
  }

  /**
   * 接单（吃单）
   */
  async takeOrder(
    orderNo: string,
    takerAccountSequence: string,
    options?: {
      quantity?: string;
      // 收款信息（接买单时由taker提供，因为taker是卖方）
      paymentMethod?: string;
      paymentAccount?: string;
      paymentQrCode?: string;
      paymentRealName?: string;
      userId?: string;
      phone?: string;
      nickname?: string;
    },
  ): Promise<C2cOrderEntity> {
    const lockKey = `c2c:take:${orderNo}`;
    const lockValue = await this.redis.acquireLock(lockKey, 30);
    if (!lockValue) {
      throw new BadRequestException('操作太频繁，请稍后再试');
    }

    try {
      // 查询订单
      const order = await this.c2cOrderRepository.findByOrderNo(orderNo);
      if (!order) {
        throw new NotFoundException('订单不存在');
      }
      if (order.status !== C2C_ORDER_STATUS.PENDING) {
        throw new BadRequestException('订单状态不正确，无法接单');
      }
      if (order.makerAccountSequence === takerAccountSequence) {
        throw new BadRequestException('不能接自己的订单');
      }

      // 如果是买单，接单方（卖方）必须提供收款信息
      if (order.type === C2C_ORDER_TYPE.BUY) {
        if (!options?.paymentMethod) {
          throw new BadRequestException('接单必须提供收款方式');
        }
        if (!options?.paymentAccount) {
          throw new BadRequestException('接单必须提供收款账号');
        }
        if (!options?.paymentRealName) {
          throw new BadRequestException('接单必须提供收款人实名');
        }
      }

      // 获取接单方账户，不存在则自动创建零余额账户
      let takerAccount = await this.tradingAccountRepository.findByAccountSequence(takerAccountSequence);
      if (!takerAccount) {
        this.logger.log(`C2C: 接单方 ${takerAccountSequence} 无交易账户，自动创建`);
        const newAccount = TradingAccountAggregate.create(takerAccountSequence);
        await this.tradingAccountRepository.save(newAccount);
        takerAccount = await this.tradingAccountRepository.findByAccountSequence(takerAccountSequence);
        if (!takerAccount) {
          throw new NotFoundException('交易账户创建失败');
        }
      }

      // #13: 支持部分成交，taker可指定数量
      const originalQuantity = new Decimal(order.quantity);
      const priceDecimal = new Decimal(order.price);

      let quantityDecimal: Decimal;
      let totalAmountDecimal: Decimal;

      if (options?.quantity) {
        quantityDecimal = new Decimal(options.quantity);
        if (quantityDecimal.gt(originalQuantity)) {
          throw new BadRequestException('接单数量不能超过订单数量');
        }
        if (quantityDecimal.lt(1)) {
          throw new BadRequestException('最小交易数量为1');
        }
        totalAmountDecimal = priceDecimal.mul(quantityDecimal);
      } else {
        quantityDecimal = originalQuantity;
        totalAmountDecimal = new Decimal(order.totalAmount);
      }

      // #13: 如果部分成交，创建剩余部分的新PENDING订单
      if (quantityDecimal.lt(originalQuantity)) {
        const remainingQuantity = originalQuantity.minus(quantityDecimal);
        const remainingTotal = priceDecimal.mul(remainingQuantity);

        const remainOrderNo = this.generateOrderNo();
        await this.c2cOrderRepository.create({
          orderNo: remainOrderNo,
          type: order.type as any,
          makerAccountSequence: order.makerAccountSequence,
          makerUserId: order.makerUserId ?? undefined,
          makerPhone: order.makerPhone ?? undefined,
          makerNickname: order.makerNickname ?? undefined,
          price: order.price,
          quantity: remainingQuantity.toString(),
          totalAmount: remainingTotal.toString(),
          paymentMethod: order.paymentMethod ?? undefined,
          paymentAccount: order.paymentAccount ?? undefined,
          paymentQrCode: order.paymentQrCode ?? undefined,
          paymentRealName: order.paymentRealName ?? undefined,
          sellerKavaAddress: order.sellerKavaAddress,
          remark: order.remark ?? undefined,
        });

        this.logger.log(`C2C部分成交: 原订单 ${orderNo} 拆分，剩余 ${remainingQuantity} 创建新订单 ${remainOrderNo}`);
      }

      // 接单方需要冻结对应资产（C2C交易的是积分值）
      if (order.type === C2C_ORDER_TYPE.BUY) {
        // 挂单方要买入积分值，接单方（卖方）需要有积分值来卖出
        const quantityMoney = new Money(quantityDecimal);
        if (takerAccount.availableCash.isLessThan(quantityMoney)) {
          throw new BadRequestException(`积分值余额不足，需要 ${quantityDecimal.toString()}，可用 ${takerAccount.availableCash.toString()}`);
        }
        // 冻结接单方的积分值
        await this.tradingAccountRepository.freezeCash(takerAccountSequence, quantityDecimal);
      } else {
        // 挂单方要卖出积分值，接单方（买方）通过外部支付绿积分，不冻结
      }

      // 计算超时时间
      const now = new Date();
      const paymentDeadline = new Date(now.getTime() + DEFAULT_PAYMENT_TIMEOUT_MINUTES * 60 * 1000);

      // 更新订单状态为已匹配
      const updateData: any = {
        takerAccountSequence,
        takerUserId: options?.userId,
        takerPhone: options?.phone,
        takerNickname: options?.nickname,
        quantity: quantityDecimal.toString(),         // #13: 更新为实际成交量
        totalAmount: totalAmountDecimal.toString(),   // #13: 更新为实际成交额
        matchedAt: now,
        paymentDeadline,
      };

      // 如果是买单，接单方（卖方）提供收款信息
      if (order.type === C2C_ORDER_TYPE.BUY) {
        updateData.paymentMethod = options?.paymentMethod;
        updateData.paymentAccount = options?.paymentAccount;
        updateData.paymentQrCode = options?.paymentQrCode;
        updateData.paymentRealName = options?.paymentRealName;
        // 获取卖方（taker）Kava 地址，买方需要用它来转绿积分
        const takerKavaAddress = await this.identityClient.getUserKavaAddress(takerAccountSequence);
        if (takerKavaAddress) {
          updateData.sellerKavaAddress = takerKavaAddress;
        }
      }

      const updatedOrder = await this.c2cOrderRepository.updateStatus(orderNo, C2C_ORDER_STATUS.MATCHED as any, updateData);

      this.logger.log(`C2C订单接单成功: ${orderNo}, 接单方: ${takerAccountSequence}, 成交数量: ${quantityDecimal.toString()}`);
      return updatedOrder!;
    } finally {
      await this.redis.releaseLock(lockKey, lockValue);
    }
  }

  /**
   * 取消订单
   */
  async cancelOrder(orderNo: string, accountSequence: string): Promise<void> {
    const lockKey = `c2c:cancel:${orderNo}`;
    const lockValue = await this.redis.acquireLock(lockKey, 30);
    if (!lockValue) {
      throw new BadRequestException('操作太频繁，请稍后再试');
    }

    try {
      const order = await this.c2cOrderRepository.findByOrderNo(orderNo);
      if (!order) {
        throw new NotFoundException('订单不存在');
      }
      if (order.makerAccountSequence !== accountSequence) {
        throw new ForbiddenException('无权取消此订单');
      }
      if (order.status !== C2C_ORDER_STATUS.PENDING) {
        throw new BadRequestException('只能取消待接单的订单');
      }

      const quantityDecimal = new Decimal(order.quantity);
      const totalAmountDecimal = new Decimal(order.totalAmount);

      // 解冻挂单方的资产
      if (order.type === C2C_ORDER_TYPE.BUY) {
        // BUY 订单未冻结买方资产（买方通过外部支付绿积分），无需解冻
      } else {
        // SELL 订单：解冻卖方的积分值
        await this.tradingAccountRepository.unfreezeCash(accountSequence, quantityDecimal);
      }

      // 更新订单状态
      await this.c2cOrderRepository.updateStatus(orderNo, C2C_ORDER_STATUS.CANCELLED as any, {
        cancelledAt: new Date(),
      });

      this.logger.log(`C2C订单取消成功: ${orderNo}`);
    } finally {
      await this.redis.releaseLock(lockKey, lockValue);
    }
  }

  /**
   * 确认付款（买方操作）
   * - BUY订单：挂单方（maker）是买方
   * - SELL订单：接单方（taker）是买方
   */
  async confirmPayment(orderNo: string, accountSequence: string): Promise<C2cOrderEntity> {
    const lockKey = `c2c:payment:${orderNo}`;
    const lockValue = await this.redis.acquireLock(lockKey, 30);
    if (!lockValue) {
      throw new BadRequestException('操作太频繁，请稍后再试');
    }

    try {
      const order = await this.c2cOrderRepository.findByOrderNo(orderNo);
      if (!order) {
        throw new NotFoundException('订单不存在');
      }
      if (order.status !== C2C_ORDER_STATUS.MATCHED) {
        throw new BadRequestException('订单状态不正确');
      }

      // 确定买方身份
      const buyerAccountSequence = order.type === C2C_ORDER_TYPE.BUY
        ? order.makerAccountSequence
        : order.takerAccountSequence;

      if (accountSequence !== buyerAccountSequence) {
        throw new ForbiddenException('只有买方可以确认付款');
      }

      // 计算确认收款超时时间
      const now = new Date();
      const confirmDeadline = new Date(now.getTime() + DEFAULT_CONFIRM_TIMEOUT_MINUTES * 60 * 1000);

      const updatedOrder = await this.c2cOrderRepository.updateStatus(orderNo, C2C_ORDER_STATUS.PAID as any, {
        paidAt: now,
        confirmDeadline,
      });

      this.logger.log(`C2C订单确认付款: ${orderNo}`);
      return updatedOrder!;
    } finally {
      await this.redis.releaseLock(lockKey, lockValue);
    }
  }

  /**
   * 确认收款（卖方操作）
   * - BUY订单：接单方（taker）是卖方
   * - SELL订单：挂单方（maker）是卖方
   */
  async confirmReceived(orderNo: string, accountSequence: string): Promise<C2cOrderEntity> {
    const lockKey = `c2c:received:${orderNo}`;
    const lockValue = await this.redis.acquireLock(lockKey, 30);
    if (!lockValue) {
      throw new BadRequestException('操作太频繁，请稍后再试');
    }

    try {
      const order = await this.c2cOrderRepository.findByOrderNo(orderNo);
      if (!order) {
        throw new NotFoundException('订单不存在');
      }
      if (order.status !== C2C_ORDER_STATUS.PAID) {
        throw new BadRequestException('订单状态不正确，买方尚未确认付款');
      }

      // 确定卖方身份
      const sellerAccountSequence = order.type === C2C_ORDER_TYPE.BUY
        ? order.takerAccountSequence
        : order.makerAccountSequence;

      if (accountSequence !== sellerAccountSequence) {
        throw new ForbiddenException('只有卖方可以确认收款');
      }

      // 执行转账（在事务中完成）
      await this.executeTransfer(order);

      const updatedOrder = await this.c2cOrderRepository.updateStatus(orderNo, C2C_ORDER_STATUS.COMPLETED as any, {
        completedAt: new Date(),
      });

      this.logger.log(`C2C订单完成: ${orderNo}`);
      return updatedOrder!;
    } finally {
      await this.redis.releaseLock(lockKey, lockValue);
    }
  }

  /**
   * 执行C2C交易转账
   */
  private async executeTransfer(order: C2cOrderEntity): Promise<void> {
    const quantityDecimal = new Decimal(order.quantity);
    const totalAmountDecimal = new Decimal(order.totalAmount);

    // 确定买卖双方
    let buyerAccountSequence: string;
    let sellerAccountSequence: string;

    if (order.type === C2C_ORDER_TYPE.BUY) {
      // BUY订单：maker是买方，taker是卖方
      buyerAccountSequence = order.makerAccountSequence;
      sellerAccountSequence = order.takerAccountSequence!;
    } else {
      // SELL订单：taker是买方，maker是卖方
      buyerAccountSequence = order.takerAccountSequence!;
      sellerAccountSequence = order.makerAccountSequence;
    }

    // 使用事务执行转账（C2C交易的是积分值，BUY和SELL都是单向划转积分值）
    await this.prisma.$transaction(async (tx) => {
      // 1. 解冻卖方积分值并扣除
      await tx.tradingAccount.update({
        where: { accountSequence: sellerAccountSequence },
        data: {
          frozenCash: { decrement: quantityDecimal.toNumber() },
          cashBalance: { decrement: quantityDecimal.toNumber() },
          totalSold: { increment: quantityDecimal.toNumber() },
        },
      });

      // 2. 买方获得积分值
      await tx.tradingAccount.update({
        where: { accountSequence: buyerAccountSequence },
        data: {
          cashBalance: { increment: quantityDecimal.toNumber() },
          totalBought: { increment: quantityDecimal.toNumber() },
        },
      });

      // 3. 记录交易流水（买方 — 积分值入账）
      const buyerAccount = await tx.tradingAccount.findUnique({
        where: { accountSequence: buyerAccountSequence },
      });
      await tx.tradingTransaction.create({
        data: {
          accountSequence: buyerAccountSequence,
          type: 'C2C_BUY',
          assetType: 'CASH',
          amount: quantityDecimal.toNumber(),
          balanceBefore: new Decimal(buyerAccount!.cashBalance).minus(quantityDecimal).toNumber(),
          balanceAfter: buyerAccount!.cashBalance,
          referenceId: order.orderNo,
          referenceType: 'C2C_ORDER',
          counterpartyType: 'USER',
          counterpartyAccountSeq: sellerAccountSequence,
          memo: `C2C买入 ${order.quantity} 积分值（绿积分支付）`,
        },
      });

      // 4. 记录交易流水（卖方 — 积分值扣除）
      const sellerAccount = await tx.tradingAccount.findUnique({
        where: { accountSequence: sellerAccountSequence },
      });
      await tx.tradingTransaction.create({
        data: {
          accountSequence: sellerAccountSequence,
          type: 'C2C_SELL',
          assetType: 'CASH',
          amount: quantityDecimal.toNumber(),
          balanceBefore: new Decimal(sellerAccount!.cashBalance).plus(quantityDecimal).toNumber(),
          balanceAfter: sellerAccount!.cashBalance,
          referenceId: order.orderNo,
          referenceType: 'C2C_ORDER',
          counterpartyType: 'USER',
          counterpartyAccountSeq: buyerAccountSequence,
          memo: `C2C卖出 ${order.quantity} 积分值（收到绿积分）`,
        },
      });
    });

    this.logger.log(`C2C交易转账完成: ${order.orderNo}, 买方: ${buyerAccountSequence}, 卖方: ${sellerAccountSequence}`);
  }

  /**
   * 获取市场订单列表（待接单的广告）
   */
  async getMarketOrders(options: {
    type?: 'BUY' | 'SELL';
    page: number;
    pageSize: number;
    excludeAccountSequence?: string;
  }): Promise<{ data: C2cOrderEntity[]; total: number; page: number; pageSize: number }> {
    const result = await this.c2cOrderRepository.findMarketOrders({
      type: options.type as any,
      page: options.page,
      pageSize: options.pageSize,
      excludeAccountSequence: options.excludeAccountSequence,
    });

    return {
      ...result,
      page: options.page,
      pageSize: options.pageSize,
    };
  }

  /**
   * 获取用户自己的订单
   */
  async getMyOrders(
    accountSequence: string,
    options: {
      status?: string;
      page: number;
      pageSize: number;
    },
  ): Promise<{ data: C2cOrderEntity[]; total: number; page: number; pageSize: number }> {
    const result = await this.c2cOrderRepository.findByAccountSequence(accountSequence, {
      status: options.status as any,
      page: options.page,
      pageSize: options.pageSize,
    });

    return {
      ...result,
      page: options.page,
      pageSize: options.pageSize,
    };
  }

  /**
   * 获取订单详情
   */
  async getOrderDetail(orderNo: string): Promise<C2cOrderEntity> {
    const order = await this.c2cOrderRepository.findByOrderNo(orderNo);
    if (!order) {
      throw new NotFoundException('订单不存在');
    }
    return order;
  }

  /**
   * 上传付款水单（买方操作）
   */
  async uploadPaymentProof(
    orderNo: string,
    accountSequence: string,
    file: { buffer: Buffer; originalname: string; mimetype: string },
  ): Promise<C2cOrderEntity> {
    const order = await this.c2cOrderRepository.findByOrderNo(orderNo);
    if (!order) {
      throw new NotFoundException('订单不存在');
    }

    // 只有 MATCHED 或 PAID 状态可以上传水单
    if (order.status !== C2C_ORDER_STATUS.MATCHED && order.status !== C2C_ORDER_STATUS.PAID) {
      throw new BadRequestException('当前订单状态不允许上传水单');
    }

    // 确定买方身份
    const buyerAccountSequence = order.type === C2C_ORDER_TYPE.BUY
      ? order.makerAccountSequence
      : order.takerAccountSequence;

    if (accountSequence !== buyerAccountSequence) {
      throw new ForbiddenException('只有买方可以上传付款水单');
    }

    // 保存文件到本地
    const uploadDir = path.resolve('./uploads/c2c-proofs');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }

    const ext = path.extname(file.originalname) || '.jpg';
    const filename = `${orderNo}-${Date.now()}${ext}`;
    const filePath = path.join(uploadDir, filename);
    fs.writeFileSync(filePath, file.buffer);

    // 生成访问URL（通过 API 网关访问）
    const proofUrl = `/api/v2/trading/c2c/proofs/${filename}`;

    const updated = await this.c2cOrderRepository.updatePaymentProof(orderNo, proofUrl);
    this.logger.log(`C2C订单上传付款水单: ${orderNo}, file: ${filename}`);
    return updated!;
  }

  /**
   * 处理超时订单（由定时任务调用）
   */
  async processExpiredOrders(): Promise<number> {
    // 计算 PENDING 订单的过期截止时间
    const pendingCutoff = new Date(Date.now() - DEFAULT_PENDING_TIMEOUT_HOURS * 60 * 60 * 1000);
    this.logger.debug(`[EXPIRY] 开始扫描超时订单, PENDING截止时间: ${pendingCutoff.toISOString()}`);

    const expiredOrders = await this.c2cOrderRepository.findExpiredOrders(pendingCutoff);

    if (expiredOrders.length === 0) {
      return 0;
    }

    this.logger.log(`[EXPIRY] 发现 ${expiredOrders.length} 个超时订单: ${expiredOrders.map(o => `${o.orderNo}(${o.type}/${o.status})`).join(', ')}`);
    let processedCount = 0;

    for (const order of expiredOrders) {
      try {
        await this.expireOrder(order);
        processedCount++;
      } catch (error) {
        this.logger.error(`[EXPIRY] 处理超时订单失败: ${order.orderNo}`, error);
      }
    }

    this.logger.log(`[EXPIRY] 本轮处理完成: 成功 ${processedCount}/${expiredOrders.length}`);
    return processedCount;
  }

  /**
   * 使订单过期（解冻资产并标记为过期）
   * 使用 Prisma 事务确保 解冻/状态更新/恢复创建 的原子性
   */
  private async expireOrder(order: C2cOrderEntity): Promise<void> {
    const lockKey = `c2c:expire:${order.orderNo}`;
    const lockValue = await this.redis.acquireLock(lockKey, 30);
    if (!lockValue) {
      this.logger.debug(`[EXPIRY] 订单 ${order.orderNo} 正被其他进程处理，跳过`);
      return;
    }

    try {
      // 重新获取订单，确保状态一致
      const freshOrder = await this.c2cOrderRepository.findByOrderNo(order.orderNo);
      if (!freshOrder) {
        this.logger.warn(`[EXPIRY] 订单 ${order.orderNo} 不存在，跳过`);
        return;
      }
      if (
        freshOrder.status !== C2C_ORDER_STATUS.PENDING &&
        freshOrder.status !== C2C_ORDER_STATUS.MATCHED &&
        freshOrder.status !== C2C_ORDER_STATUS.PAID
      ) {
        this.logger.debug(`[EXPIRY] 订单 ${order.orderNo} 状态已变为 ${freshOrder.status}，无需处理`);
        return;
      }

      const quantityDecimal = new Decimal(freshOrder.quantity);
      const shouldRestore = freshOrder.status === C2C_ORDER_STATUS.MATCHED || freshOrder.status === C2C_ORDER_STATUS.PAID;
      const isSell = freshOrder.type === C2C_ORDER_TYPE.SELL;
      let restoreOrderNo: string | null = null;

      this.logger.log(
        `[EXPIRY] 开始处理订单 ${freshOrder.orderNo}: ` +
        `类型=${freshOrder.type}, 状态=${freshOrder.status}, ` +
        `数量=${freshOrder.quantity}, 价格=${freshOrder.price}, ` +
        `maker=${freshOrder.makerAccountSequence}, taker=${freshOrder.takerAccountSequence || '无'}, ` +
        `需恢复=${shouldRestore}`,
      );

      await this.prisma.$transaction(async (tx) => {
        // 1. 解冻卖方的积分值（如果需要）
        if (freshOrder.status === C2C_ORDER_STATUS.PENDING) {
          if (isSell) {
            this.logger.log(`[EXPIRY][TX] 步骤1: 解冻 PENDING SELL maker ${freshOrder.makerAccountSequence} 的 frozenCash -= ${quantityDecimal}`);
            await tx.tradingAccount.update({
              where: { accountSequence: freshOrder.makerAccountSequence },
              data: { frozenCash: { decrement: quantityDecimal.toNumber() } },
            });
          } else {
            this.logger.debug(`[EXPIRY][TX] 步骤1: PENDING BUY 无冻结资产，跳过解冻`);
          }
        } else if (!isSell && freshOrder.takerAccountSequence) {
          // MATCHED/PAID BUY：解冻 taker（卖方）
          this.logger.log(`[EXPIRY][TX] 步骤1: 解冻 ${freshOrder.status} BUY taker ${freshOrder.takerAccountSequence} 的 frozenCash -= ${quantityDecimal}`);
          await tx.tradingAccount.update({
            where: { accountSequence: freshOrder.takerAccountSequence },
            data: { frozenCash: { decrement: quantityDecimal.toNumber() } },
          });
        } else if (isSell && shouldRestore) {
          this.logger.log(`[EXPIRY][TX] 步骤1: ${freshOrder.status} SELL 保持冻结不变，冻结量将转给恢复的 PENDING 订单`);
        }

        // 2. 标记订单为过期
        this.logger.log(`[EXPIRY][TX] 步骤2: 标记订单 ${freshOrder.orderNo} 状态 ${freshOrder.status} -> EXPIRED`);
        await tx.c2cOrder.update({
          where: { orderNo: freshOrder.orderNo },
          data: {
            status: C2C_ORDER_STATUS.EXPIRED as any,
            expiredAt: new Date(),
          },
        });

        // 3. MATCHED/PAID 订单恢复：优先合并到已有的同 maker/type/price 的 PENDING 订单
        if (shouldRestore) {
          const priceDecimal = new Decimal(freshOrder.price);

          // 查找是否已有可合并的 PENDING 订单（同 maker + 同类型 + 同价格）
          let existingPending = await tx.c2cOrder.findFirst({
            where: {
              makerAccountSequence: freshOrder.makerAccountSequence,
              type: freshOrder.type as any,
              status: C2C_ORDER_STATUS.PENDING as any,
              price: freshOrder.price,
            },
          });

          if (existingPending) {
            // 合并到已有 PENDING 订单：增加数量和总金额
            const existingQty = new Decimal(existingPending.quantity.toString());
            const mergedQty = existingQty.plus(quantityDecimal);
            const mergedTotal = priceDecimal.mul(mergedQty).toString();

            this.logger.log(
              `[EXPIRY][TX] 步骤3: 尝试合并到 PENDING 订单 ${existingPending.orderNo}, ` +
              `原数量=${existingQty} + 恢复=${quantityDecimal} = ${mergedQty}`,
            );

            // 用 updateMany + status 条件防止竞态：如果订单在 findFirst 后被 takeOrder 接走，count=0
            const updateResult = await tx.c2cOrder.updateMany({
              where: {
                orderNo: existingPending.orderNo,
                status: C2C_ORDER_STATUS.PENDING as any,
              },
              data: {
                quantity: mergedQty.toString(),
                totalAmount: mergedTotal,
              },
            });

            if (updateResult.count > 0) {
              restoreOrderNo = existingPending.orderNo;
              this.logger.log(`[EXPIRY][TX] 步骤3: 合并成功`);
            } else {
              // 订单已被接走（状态不再是 PENDING），回退到创建新订单
              this.logger.warn(`[EXPIRY][TX] 步骤3: 订单 ${existingPending.orderNo} 已被接走，改为创建新订单`);
              existingPending = null; // fall through to create
            }
          }

          if (shouldRestore && !restoreOrderNo) {
            // 无可合并订单，创建新的 PENDING 订单
            restoreOrderNo = this.generateOrderNo();
            const totalAmount = priceDecimal.mul(quantityDecimal).toString();

            this.logger.log(
              `[EXPIRY][TX] 步骤3: 创建新 PENDING 订单 ${restoreOrderNo}, ` +
              `类型=${freshOrder.type}, maker=${freshOrder.makerAccountSequence}, ` +
              `数量=${quantityDecimal}, 总金额=${totalAmount}`,
            );

            await tx.c2cOrder.create({
              data: {
                orderNo: restoreOrderNo,
                type: freshOrder.type as any,
                status: C2C_ORDER_STATUS.PENDING as any,
                makerAccountSequence: freshOrder.makerAccountSequence,
                makerUserId: freshOrder.makerUserId,
                makerPhone: freshOrder.makerPhone,
                makerNickname: freshOrder.makerNickname,
                price: freshOrder.price,
                quantity: quantityDecimal.toString(),
                totalAmount,
                minAmount: '0',
                maxAmount: '0',
                paymentMethod: isSell ? freshOrder.paymentMethod : null,
                paymentAccount: isSell ? freshOrder.paymentAccount : null,
                paymentQrCode: isSell ? freshOrder.paymentQrCode : null,
                paymentRealName: isSell ? freshOrder.paymentRealName : null,
                sellerKavaAddress: isSell ? freshOrder.sellerKavaAddress : null,
                remark: freshOrder.remark,
              },
            });
          }
        } else {
          this.logger.debug(`[EXPIRY][TX] 步骤3: PENDING 订单无需恢复`);
        }
      });

      // 事务成功后记日志
      this.logger.log(
        `[EXPIRY] 事务提交成功: 订单 ${freshOrder.orderNo} (${freshOrder.type}/${freshOrder.status}) -> EXPIRED` +
        (restoreOrderNo ? `, 恢复为 ${restoreOrderNo} (PENDING, 数量=${quantityDecimal})` : ''),
      );
    } catch (error: any) {
      // 事务失败 = 全部回滚，不会出现不一致状态
      this.logger.error(
        `[EXPIRY] 事务失败，已回滚: 订单=${order.orderNo}, ` +
        `错误=${error.message}`,
        error.stack,
      );
      throw error;
    } finally {
      await this.redis.releaseLock(lockKey, lockValue);
    }
  }
}
