import { Injectable, Logger } from '@nestjs/common';
import { OrderRepository } from '../../infrastructure/persistence/repositories/order.repository';
import { TradingAccountRepository } from '../../infrastructure/persistence/repositories/trading-account.repository';
import { CirculationPoolRepository } from '../../infrastructure/persistence/repositories/circulation-pool.repository';
import { OutboxRepository } from '../../infrastructure/persistence/repositories/outbox.repository';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { RedisService } from '../../infrastructure/redis/redis.service';
import { OrderAggregate, OrderType, OrderStatus, OrderSource } from '../../domain/aggregates/order.aggregate';
import { TradingAccountAggregate } from '../../domain/aggregates/trading-account.aggregate';
import { MatchingEngineService } from '../../domain/services/matching-engine.service';
import { Money } from '../../domain/value-objects/money.vo';
import { BurnService } from './burn.service';
import { PriceService } from './price.service';
// [2026-03-04] 新增：预种卖出限制检查
import { TradingSellRestrictionService } from './sell-restriction.service';
import {
  TradingEventTypes,
  TradingTopics,
  OrderCreatedPayload,
  OrderCancelledPayload,
  TradeExecutedPayload,
} from '../../domain/events/trading.events';

// 交易手续费率：10%
const TRADE_FEE_RATE = 0.1;

@Injectable()
export class OrderService {
  private readonly logger = new Logger(OrderService.name);
  private readonly matchingEngine = new MatchingEngineService();

  constructor(
    private readonly orderRepository: OrderRepository,
    private readonly accountRepository: TradingAccountRepository,
    private readonly circulationPoolRepository: CirculationPoolRepository,
    private readonly outboxRepository: OutboxRepository,
    private readonly prisma: PrismaService,
    private readonly redis: RedisService,
    private readonly burnService: BurnService,
    private readonly priceService: PriceService,
    private readonly sellRestrictionService: TradingSellRestrictionService,
  ) {}

  async createOrder(
    accountSequence: string,
    type: OrderType,
    price: string,
    quantity: string,
    source: OrderSource = OrderSource.USER,
    sourceLabel?: string,
  ): Promise<{ orderId: string; orderNo: string; status: OrderStatus; filledQuantity: string }> {
    const lockValue = await this.redis.acquireLock(`order:create:${accountSequence}`, 10);
    if (!lockValue) {
      throw new Error('System busy, please try again');
    }

    try {
      // 验证账户
      let account = await this.accountRepository.findByAccountSequence(accountSequence);
      if (!account) {
        account = TradingAccountAggregate.create(accountSequence);
      }

      const priceAmount = new Money(price);
      const quantityAmount = new Money(quantity);
      const totalCost = quantityAmount.multiply(priceAmount.value);

      // [2026-03-04] 预种卖出限制检查（fail-open：contribution-service 不可用时允许卖出）
      if (type === OrderType.SELL) {
        const restricted = await this.sellRestrictionService.isRestricted(accountSequence);
        if (restricted) {
          throw new Error('预种积分股暂时不可卖出，请先完成预种合并（满10份合成1棵树后即可卖出）');
        }
      }

      // 检查余额并冻结
      if (type === OrderType.BUY) {
        if (account.availableCash.isLessThan(totalCost)) {
          throw new Error('Insufficient cash balance');
        }
      } else {
        if (account.availableShares.isLessThan(quantityAmount)) {
          throw new Error('Insufficient share balance');
        }
      }

      // 生成订单号
      const orderNo = this.generateOrderNo();

      // 创建订单
      const order = OrderAggregate.create(orderNo, accountSequence, type, priceAmount, quantityAmount, source, sourceLabel);

      // 冻结资产
      if (type === OrderType.BUY) {
        account.freezeCash(totalCost, orderNo);
      } else {
        account.freezeShares(quantityAmount, orderNo);
      }

      // 保存订单和账户
      const orderId = await this.orderRepository.save(order);
      await this.accountRepository.save(account);

      // 发布订单创建事件
      await this.publishOrderCreatedEvent(orderId, order);

      // 重新从数据库获取订单（确保有id）
      const savedOrder = await this.orderRepository.findByOrderNo(orderNo);
      if (!savedOrder) {
        throw new Error('Failed to retrieve saved order');
      }

      // 尝试撮合
      await this.tryMatch(savedOrder);

      // 获取最新订单状态
      const updatedOrder = await this.orderRepository.findByOrderNo(orderNo);

      return {
        orderId,
        orderNo,
        status: updatedOrder?.status || order.status,
        filledQuantity: updatedOrder?.filledQuantity.toString() || '0',
      };
    } finally {
      await this.redis.releaseLock(`order:create:${accountSequence}`, lockValue);
    }
  }

  async cancelOrder(accountSequence: string, orderNo: string): Promise<void> {
    const order = await this.orderRepository.findByOrderNo(orderNo);
    if (!order) {
      throw new Error('Order not found');
    }
    if (order.accountSequence !== accountSequence) {
      throw new Error('Unauthorized');
    }

    const account = await this.accountRepository.findByAccountSequence(accountSequence);
    if (!account) {
      throw new Error('Account not found');
    }

    // 取消订单
    order.cancel();

    // 解冻资产
    if (order.type === OrderType.BUY) {
      account.unfreezeCash(order.lockedAmount, orderNo);
    } else {
      account.unfreezeShares(order.remainingQuantity, orderNo);
    }

    await this.orderRepository.save(order);
    await this.accountRepository.save(account);

    // 发布订单取消事件
    await this.publishOrderCancelledEvent(order);
  }

  private async tryMatch(incomingOrder: OrderAggregate): Promise<void> {
    const lockValue = await this.redis.acquireLock('order:matching', 30);
    if (!lockValue) return;

    try {
      const oppositeType = incomingOrder.type === OrderType.BUY ? OrderType.SELL : OrderType.BUY;
      const orderBook = await this.orderRepository.findActiveOrders(oppositeType);

      const matches = this.matchingEngine.findMatchingOrders(incomingOrder, orderBook);

      // 查询做市商配置（用于判断买方是否为做市商 + 手续费存入）
      const mmConfig = await this.prisma.marketMakerConfig.findUnique({
        where: { name: 'MAIN_MARKET_MAKER' },
      });

      for (const match of matches) {
        const tradeQuantity = match.trade.quantity;
        let burnQuantity = Money.zero();
        let effectiveQuantity = tradeQuantity;
        const isBuyerMarketMaker = mmConfig?.accountSequence === match.buyOrder.accountSequence;

        // 如果是卖出成交，执行销毁逻辑
        // 卖出的销毁量 = 卖出积分股 × 倍数
        // 卖出交易额 = (卖出量 + 卖出销毁量) × 积分股价
        if (match.sellOrder) {
          try {
            const burnResult = await this.burnService.executeSellBurn(
              tradeQuantity,
              match.sellOrder.accountSequence,
              match.sellOrder.orderNo,
            );
            burnQuantity = burnResult.burnQuantity;
            effectiveQuantity = new Money(tradeQuantity.value.plus(burnQuantity.value));

            this.logger.log(
              `Sell burn executed: sellQty=${tradeQuantity.toFixed(8)}, ` +
                `burnQty=${burnQuantity.toFixed(8)}, effectiveQty=${effectiveQuantity.toFixed(8)}`,
            );
          } catch (error) {
            this.logger.warn(`Sell burn failed, continuing without burn: ${error}`);
          }
        }

        // 计算交易额
        // 买方支付：原始数量 × 价格（买方冻结的是这个金额）
        const buyerPayAmount = new Money(tradeQuantity.value.times(match.trade.price.value));
        // 卖方总收益（含销毁倍数）：有效数量 × 价格
        const sellerGrossAmount = new Money(effectiveQuantity.value.times(match.trade.price.value));
        // 交易手续费（10%）：从卖方收益中扣除
        const tradeFee = new Money(sellerGrossAmount.value.times(TRADE_FEE_RATE));
        // 卖方实际收到：总收益 - 手续费
        const sellerReceiveAmount = new Money(sellerGrossAmount.value.minus(tradeFee.value));

        // ========== 使用事务确保成交记录、订单状态、账户余额的原子性 ==========
        // 修复 Bug：之前没有使用事务，导致成交记录创建成功但账户余额更新可能失败
        await this.prisma.$transaction(async (tx) => {
          // 1. 保存成交记录
          await tx.trade.create({
            data: {
              tradeNo: match.trade.tradeNo,
              buyOrderId: match.buyOrder.id!,
              sellOrderId: match.sellOrder.id!,
              buyerSequence: match.buyOrder.accountSequence,
              sellerSequence: match.sellOrder.accountSequence,
              price: match.trade.price.value,
              quantity: effectiveQuantity.value,
              originalQuantity: tradeQuantity.value,
              burnQuantity: burnQuantity.value,
              effectiveQty: effectiveQuantity.value,
              amount: sellerReceiveAmount.value,
              fee: tradeFee.value,
              buyerSource: match.buyOrder.source,
              sellerSource: match.sellOrder.source,
            },
          });

          // 2. 更新买单状态
          await tx.order.update({
            where: { id: match.buyOrder.id! },
            data: {
              status: match.buyOrder.status,
              filledQuantity: match.buyOrder.filledQuantity.value,
              remainingQuantity: match.buyOrder.remainingQuantity.value,
              averagePrice: match.buyOrder.averagePrice.value,
              totalAmount: match.buyOrder.totalAmount.value,
              completedAt: match.buyOrder.completedAt,
            },
          });

          // 3. 更新卖单状态（含销毁信息）
          await tx.order.update({
            where: { id: match.sellOrder.id! },
            data: {
              status: match.sellOrder.status,
              filledQuantity: match.sellOrder.filledQuantity.value,
              remainingQuantity: match.sellOrder.remainingQuantity.value,
              averagePrice: match.sellOrder.averagePrice.value,
              totalAmount: match.sellOrder.totalAmount.value,
              burnQuantity: burnQuantity.value,
              burnMultiplier: burnQuantity.isZero()
                ? 0
                : burnQuantity.value.dividedBy(match.sellOrder.filledQuantity.value),
              effectiveQuantity: effectiveQuantity.value,
              completedAt: match.sellOrder.completedAt,
            },
          });

          // 4. 更新买方账户
          // 做市商吃单时：
          //   - 支付 sellerGrossAmount（含销毁倍数的交易总额），不是仅原始数量×价格
          //   - 积分股不进做市商账户，只进流通池
          // 普通用户买入时：
          //   - 支付 buyerPayAmount（原始数量×价格）
          //   - 积分股直接进入买方账户
          const buyerAccountRecord = await tx.tradingAccount.findUnique({
            where: { accountSequence: match.buyOrder.accountSequence },
          });
          if (buyerAccountRecord) {
            // 做市商实际支付 = 交易总额（含销毁倍数）；普通用户支付 = 原始数量×价格
            const actualBuyerCost = isBuyerMarketMaker ? sellerGrossAmount : buyerPayAmount;
            // frozenCash 释放的是下单时冻结的原始金额
            const newFrozenCash = Number(buyerAccountRecord.frozenCash) - buyerPayAmount.value.toNumber();
            const newCashBalance = Number(buyerAccountRecord.cashBalance) - actualBuyerCost.value.toNumber();
            const newShareBalance = isBuyerMarketMaker
              ? Number(buyerAccountRecord.shareBalance)
              : Number(buyerAccountRecord.shareBalance) + tradeQuantity.value.toNumber();
            const newTotalBought = Number(buyerAccountRecord.totalBought) + tradeQuantity.value.toNumber();

            await tx.tradingAccount.update({
              where: { accountSequence: match.buyOrder.accountSequence },
              data: {
                frozenCash: newFrozenCash,
                cashBalance: newCashBalance,
                shareBalance: newShareBalance,
                totalBought: newTotalBought,
              },
            });

            // 记录买方交易流水
            if (isBuyerMarketMaker) {
              // 做市商：记录现金支出（交易总额）
              await tx.tradingTransaction.create({
                data: {
                  accountSequence: match.buyOrder.accountSequence,
                  type: 'BUY',
                  assetType: 'CASH',
                  amount: actualBuyerCost.value,
                  balanceBefore: buyerAccountRecord.cashBalance,
                  balanceAfter: newCashBalance,
                  referenceId: match.trade.tradeNo,
                  referenceType: 'TRADE',
                  description: `做市商吃单(积分股→流通池), 交易总额${sellerGrossAmount.toFixed(4)}`,
                },
              });
            } else {
              // 普通用户：记录积分股收入
              await tx.tradingTransaction.create({
                data: {
                  accountSequence: match.buyOrder.accountSequence,
                  type: 'BUY',
                  assetType: 'SHARE',
                  amount: tradeQuantity.value,
                  balanceBefore: buyerAccountRecord.shareBalance,
                  balanceAfter: newShareBalance,
                  referenceId: match.trade.tradeNo,
                  referenceType: 'TRADE',
                  description: '买入成交',
                },
              });
            }
          }

          // 5. 更新卖方账户（扣除冻结积分股，增加现金）
          const sellerAccountRecord = await tx.tradingAccount.findUnique({
            where: { accountSequence: match.sellOrder.accountSequence },
          });
          if (sellerAccountRecord) {
            const newFrozenShares = Number(sellerAccountRecord.frozenShares) - tradeQuantity.value.toNumber();
            const newShareBalance = Number(sellerAccountRecord.shareBalance) - tradeQuantity.value.toNumber();
            const newCashBalance = Number(sellerAccountRecord.cashBalance) + sellerReceiveAmount.value.toNumber();
            const newTotalSold = Number(sellerAccountRecord.totalSold) + tradeQuantity.value.toNumber();

            await tx.tradingAccount.update({
              where: { accountSequence: match.sellOrder.accountSequence },
              data: {
                frozenShares: newFrozenShares,
                shareBalance: newShareBalance,
                cashBalance: newCashBalance,
                totalSold: newTotalSold,
              },
            });

            // 记录卖方交易流水
            await tx.tradingTransaction.create({
              data: {
                accountSequence: match.sellOrder.accountSequence,
                type: 'SELL',
                assetType: 'SHARE',
                amount: tradeQuantity.value,
                balanceBefore: sellerAccountRecord.shareBalance,
                balanceAfter: newShareBalance,
                referenceId: match.trade.tradeNo,
                referenceType: 'TRADE',
                description: '卖出成交',
              },
            });
          }
        }, {
          timeout: 30000, // 30秒超时
        });
        // ========== 事务结束 ==========

        // 做市商吃单时：卖出的积分股进入流通池（做市商不持有积分股）
        // 普通用户买入时：买方已在事务内获得积分股，不重复计入流通池
        if (isBuyerMarketMaker) {
          try {
            await this.circulationPoolRepository.addSharesFromSell(
              tradeQuantity,
              match.sellOrder.accountSequence,
              match.sellOrder.id!,
              `做市商吃单→流通池, 交易号${match.trade.tradeNo}`,
            );
          } catch (error) {
            this.logger.warn(`Failed to add shares to circulation pool: ${error}`);
          }
        }

        // 10%手续费存入做市商账户（做市商的 cashBalance 即积分值池）
        try {
          if (mmConfig) {
            await this.prisma.tradingAccount.update({
              where: { accountSequence: mmConfig.accountSequence },
              data: { cashBalance: { increment: tradeFee.value } },
            });
            this.logger.debug(
              `Trade fee deposited to market maker: ${tradeFee.toFixed(8)}, tradeNo=${match.trade.tradeNo}`,
            );
          }
        } catch (error) {
          this.logger.error(`Failed to deposit trade fee to market maker: ${error}`);
        }

        this.logger.log(
          `Trade executed: ${match.trade.tradeNo}, price=${match.trade.price.toFixed(8)}, ` +
            `qty=${tradeQuantity.toFixed(8)}, burn=${burnQuantity.toFixed(8)}, ` +
            `buyerPay=${buyerPayAmount.toFixed(8)}, fee=${tradeFee.toFixed(8)}, sellerReceive=${sellerReceiveAmount.toFixed(8)}`,
        );

        // 发布成交事件
        await this.publishTradeExecutedEvent(
          match.trade.tradeNo,
          match.buyOrder,
          match.sellOrder,
          match.trade.price,
          tradeQuantity,
          sellerReceiveAmount,
          burnQuantity,
          effectiveQuantity,
        );
      }
    } finally {
      await this.redis.releaseLock('order:matching', lockValue);
    }
  }

  private generateOrderNo(): string {
    const timestamp = Date.now().toString(36);
    const random = Math.random().toString(36).substring(2, 8);
    return `O${timestamp}${random}`.toUpperCase();
  }

  // ==================== 事件发布方法 ====================

  /**
   * 发布订单创建事件
   */
  private async publishOrderCreatedEvent(orderId: string, order: OrderAggregate): Promise<void> {
    try {
      const payload: OrderCreatedPayload = {
        orderId,
        orderNo: order.orderNo,
        accountSequence: order.accountSequence,
        type: order.type,
        price: order.price.toString(),
        quantity: order.quantity.toString(),
        createdAt: new Date().toISOString(),
      };

      await this.outboxRepository.create({
        aggregateType: 'Order',
        aggregateId: orderId,
        eventType: TradingEventTypes.ORDER_CREATED,
        payload,
        topic: TradingTopics.ORDERS,
        key: order.accountSequence,
      });

      this.logger.debug(`Published OrderCreated event for order ${order.orderNo}`);
    } catch (error) {
      this.logger.error(`Failed to publish OrderCreated event: ${error}`);
    }
  }

  /**
   * 发布订单取消事件
   */
  private async publishOrderCancelledEvent(order: OrderAggregate): Promise<void> {
    try {
      const payload: OrderCancelledPayload = {
        orderId: order.id!,
        orderNo: order.orderNo,
        accountSequence: order.accountSequence,
        type: order.type,
        cancelledQuantity: order.remainingQuantity.toString(),
        cancelledAt: new Date().toISOString(),
      };

      await this.outboxRepository.create({
        aggregateType: 'Order',
        aggregateId: order.id!,
        eventType: TradingEventTypes.ORDER_CANCELLED,
        payload,
        topic: TradingTopics.ORDERS,
        key: order.accountSequence,
      });

      this.logger.debug(`Published OrderCancelled event for order ${order.orderNo}`);
    } catch (error) {
      this.logger.error(`Failed to publish OrderCancelled event: ${error}`);
    }
  }

  /**
   * 发布成交事件
   */
  private async publishTradeExecutedEvent(
    tradeNo: string,
    buyOrder: OrderAggregate,
    sellOrder: OrderAggregate,
    price: Money,
    quantity: Money,
    amount: Money,
    burnQuantity: Money,
    effectiveQuantity: Money,
  ): Promise<void> {
    try {
      // 使用 tradeNo 查找刚创建的 trade 获取 id
      const trade = await this.prisma.trade.findUnique({ where: { tradeNo } });
      if (!trade) {
        this.logger.warn(`Trade not found for event publishing: ${tradeNo}`);
        return;
      }

      const payload: TradeExecutedPayload = {
        tradeId: trade.id,
        tradeNo,
        buyOrderId: buyOrder.id!,
        sellOrderId: sellOrder.id!,
        buyerSequence: buyOrder.accountSequence,
        sellerSequence: sellOrder.accountSequence,
        price: price.toString(),
        quantity: quantity.toString(),
        amount: amount.toString(),
        burnQuantity: burnQuantity.toString(),
        effectiveQuantity: effectiveQuantity.toString(),
        createdAt: new Date().toISOString(),
      };

      await this.outboxRepository.create({
        aggregateType: 'Trade',
        aggregateId: trade.id,
        eventType: TradingEventTypes.TRADE_EXECUTED,
        payload,
        topic: TradingTopics.TRADES,
        key: tradeNo,
      });

      this.logger.debug(`Published TradeExecuted event for trade ${tradeNo}`);
    } catch (error) {
      this.logger.error(`Failed to publish TradeExecuted event: ${error}`);
    }
  }
}
