import { Injectable, Inject, Logger } from '@nestjs/common';
import { RewardLedgerEntry } from '../../domain/aggregates/reward-ledger-entry/reward-ledger-entry.aggregate';
import { RewardCalculationService } from '../../domain/services/reward-calculation.service';
import { RewardExpirationService } from '../../domain/services/reward-expiration.service';
import type { IRewardLedgerEntryRepository } from '../../domain/repositories/reward-ledger-entry.repository.interface';
import { REWARD_LEDGER_ENTRY_REPOSITORY } from '../../domain/repositories/reward-ledger-entry.repository.interface';
import type { IRewardSummaryRepository } from '../../domain/repositories/reward-summary.repository.interface';
import { REWARD_SUMMARY_REPOSITORY } from '../../domain/repositories/reward-summary.repository.interface';
import { RewardStatus } from '../../domain/value-objects/reward-status.enum';
import { RightType } from '../../domain/value-objects/right-type.enum';
import { Money } from '../../domain/value-objects/money.vo';
import { Hashpower } from '../../domain/value-objects/hashpower.vo';
import { EventPublisherService } from '../../infrastructure/kafka/event-publisher.service';
import { WalletServiceClient } from '../../infrastructure/external/wallet-service/wallet-service.client';
import { OutboxRepository, OutboxEventData } from '../../infrastructure/persistence/repositories/outbox.repository';
import { SettlementRecordRepository, SettlementRecordDto } from '../../infrastructure/persistence/repositories/settlement-record.repository';
import { RewardSummary } from '../../domain/aggregates/reward-summary/reward-summary.aggregate';
// [2026-01-04] 新增：用于过期收益统计查询
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';

// 总部社区账户ID
const HEADQUARTERS_COMMUNITY_USER_ID = BigInt(1);

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

  constructor(
    private readonly rewardCalculationService: RewardCalculationService,
    private readonly rewardExpirationService: RewardExpirationService,
    @Inject(REWARD_LEDGER_ENTRY_REPOSITORY)
    private readonly rewardLedgerEntryRepository: IRewardLedgerEntryRepository,
    @Inject(REWARD_SUMMARY_REPOSITORY)
    private readonly rewardSummaryRepository: IRewardSummaryRepository,
    private readonly eventPublisher: EventPublisherService,
    private readonly walletService: WalletServiceClient,
    private readonly outboxRepository: OutboxRepository,
    private readonly settlementRecordRepository: SettlementRecordRepository,
    // [2026-01-04] 新增：用于过期收益统计查询
    private readonly prisma: PrismaService,
  ) {}

  /**
   * 分配奖励 (响应 planting.order.paid 事件)
   *
   * 事件来源：referral-service 在确认扣款后发送
   *
   * 核心职责：
   * 1. 计算考核后的奖励分配方案（调用 authorization-service）
   * 2. 调用 wallet-service 执行真正的资金分配
   * 3. 保存奖励流水记录
   *
   * 注意：扣款确认由 referral-service 在发送此事件前完成
   */
  async distributeRewards(params: {
    sourceOrderNo: string;  // 订单号是字符串格式如 PLT1765391584505Q0Q6QD
    sourceUserId: bigint;
    sourceAccountSequence?: string;  // 跨服务关联标识
    treeCount: number;
    provinceCode: string;
    cityCode: string;
    priceSupplement?: number; // [2026-02-26] 总部运营成本压力涨价（每棵树加价金额），归总部 (S0000000001)
  }): Promise<void> {
    this.logger.log(`Distributing rewards for order ${params.sourceOrderNo}, accountSequence=${params.sourceAccountSequence}`);

    // 幂等性检查：如果该订单已经分配过奖励，跳过处理
    const existingRewards = await this.rewardLedgerEntryRepository.findBySourceOrderNo(params.sourceOrderNo);
    if (existingRewards.length > 0) {
      this.logger.warn(`Order ${params.sourceOrderNo} already has ${existingRewards.length} rewards distributed, skipping (idempotent)`);
      return;
    }

    // 1. 计算所有奖励（包含考核逻辑，调用 authorization-service）
    const rewards = await this.rewardCalculationService.calculateRewards(params);

    // 2. 调用 wallet-service 执行真正的资金分配
    // 字段映射：targetType=USER/SYSTEM, targetId=accountSequence, allocationType=rightType
    const allocations: import('../../infrastructure/external/wallet-service/wallet-service.client').FundAllocationItem[] = rewards.map(reward => ({
      targetType: (reward.accountSequence.startsWith('S') ? 'SYSTEM' : 'USER') as 'USER' | 'SYSTEM',
      targetId: reward.accountSequence,  // 使用 accountSequence 而不是 userId
      allocationType: reward.rewardSource.rightType,
      amount: reward.usdtAmount.amount,
      hashpowerPercent: reward.hashpowerAmount.value > 0 ? reward.hashpowerAmount.value : undefined,
      metadata: {
        rightType: reward.rewardSource.rightType,
        sourceOrderNo: params.sourceOrderNo,
        sourceUserId: params.sourceUserId.toString(),
        // [2026-01-04] 新增字段：用于系统账户报表统计，支持追溯每笔收益的来源
        // 回滚方式：删除以下4行即可恢复原状
        sourceAccountSequence: params.sourceAccountSequence ?? null,  // 来源用户账户序列号
        treeCount: params.treeCount,                                  // 认种数量
        provinceCode: params.provinceCode,                            // 认种省份代码
        cityCode: params.cityCode,                                    // 认种城市代码
        memo: reward.memo,
      },
    }));

    const allocateResult = await this.walletService.allocateFunds({
      orderId: params.sourceOrderNo,
      allocations,
    });

    if (!allocateResult.success) {
      this.logger.error(`Failed to allocate funds for order ${params.sourceOrderNo}: ${allocateResult.error}`);
      throw new Error(`资金分配失败: ${allocateResult.error}`);
    }

    this.logger.log(`Wallet allocation completed for order ${params.sourceOrderNo}`);

    // 3. 保存奖励流水
    await this.rewardLedgerEntryRepository.saveAll(rewards);

    // 4. 更新各用户的汇总数据
    const userIds = [...new Set(rewards.map(r => r.userId))];
    const updatedSummaries: RewardSummary[] = [];

    for (const userId of userIds) {
      const userRewards = rewards.filter(r => r.userId === userId);
      const accountSequence = userRewards[0].accountSequence;
      const summary = await this.rewardSummaryRepository.getOrCreate(userId, accountSequence);

      for (const reward of userRewards) {
        if (reward.isPending) {
          summary.addPending(
            reward.usdtAmount,
            reward.hashpowerAmount,
            reward.expireAt!,
          );
        } else if (reward.isSettleable) {
          summary.addSettleable(reward.usdtAmount, reward.hashpowerAmount);
        }
      }

      await this.rewardSummaryRepository.save(summary);
      updatedSummaries.push(summary);
    }

    // 5. 发布领域事件
    for (const reward of rewards) {
      await this.eventPublisher.publishAll(reward.domainEvents);
      reward.clearDomainEvents();
    }

    this.logger.log(`Distributed ${rewards.length} rewards for order ${params.sourceOrderNo}`);
  }

  /**
   * 分配奖励到系统账户 (响应 planting.order.expired 事件)
   *
   * 事件来源：referral-service 在确认扣款后发送
   *
   * 与正常分配的区别：
   * - 系统费用（成本费、运营费、底池、总部基础费）：正常分配
   * - 用户权益（分享、省团队、市团队、社区、省区域、市区域）：全部进入系统默认账户
   *
   * 系统默认账户规则：
   * - 分享权益 → S0000000005（分享权益池）
   * - 省团队权益 → 7+省代码（省团队默认账户）
   * - 市团队权益 → 6+市代码（市团队默认账户）
   * - 社区权益 → S0000000001（总部社区）
   * - 省区域权益 → 9+省代码（省区域账户）
   * - 市区域权益 → 8+市代码（市区域账户）
   *
   * 注意：扣款确认由 referral-service 在发送此事件前完成
   */
  async distributeRewardsForExpiredContract(params: {
    sourceOrderNo: string;
    sourceUserId: bigint;
    sourceAccountSequence?: string;
    treeCount: number;
    provinceCode: string;
    cityCode: string;
  }): Promise<void> {
    this.logger.log(`Distributing rewards for EXPIRED contract, order ${params.sourceOrderNo}`);

    // 幂等性检查：如果该订单已经分配过奖励，跳过处理
    const existingRewards = await this.rewardLedgerEntryRepository.findBySourceOrderNo(params.sourceOrderNo);
    if (existingRewards.length > 0) {
      this.logger.warn(`Expired contract order ${params.sourceOrderNo} already has ${existingRewards.length} rewards distributed, skipping (idempotent)`);
      return;
    }

    // 1. 计算奖励，但使用系统账户作为用户权益的接收方
    const rewards = await this.rewardCalculationService.calculateRewardsForExpiredContract(params);

    // 2. 调用 wallet-service 执行资金分配
    const allocations: import('../../infrastructure/external/wallet-service/wallet-service.client').FundAllocationItem[] = rewards.map(reward => ({
      targetType: (reward.accountSequence.startsWith('S') || /^\d+$/.test(reward.accountSequence) ? 'SYSTEM' : 'USER') as 'USER' | 'SYSTEM',
      targetId: reward.accountSequence,
      allocationType: reward.rewardSource.rightType,
      amount: reward.usdtAmount.amount,
      hashpowerPercent: reward.hashpowerAmount.value > 0 ? reward.hashpowerAmount.value : undefined,
      metadata: {
        rightType: reward.rewardSource.rightType,
        sourceOrderNo: params.sourceOrderNo,
        sourceUserId: params.sourceUserId.toString(),
        // [2026-01-04] 新增字段：用于系统账户报表统计，支持追溯每笔收益的来源
        // 回滚方式：删除以下4行即可恢复原状
        sourceAccountSequence: params.sourceAccountSequence ?? null,  // 来源用户账户序列号
        treeCount: params.treeCount,                                  // 认种数量
        provinceCode: params.provinceCode,                            // 认种省份代码
        cityCode: params.cityCode,                                    // 认种城市代码
        memo: reward.memo,
        reason: 'CONTRACT_EXPIRED', // 标记为合同超时
      },
    }));

    const allocateResult = await this.walletService.allocateFunds({
      orderId: params.sourceOrderNo,
      allocations,
    });

    if (!allocateResult.success) {
      this.logger.error(`Failed to allocate funds for expired contract order ${params.sourceOrderNo}: ${allocateResult.error}`);
      throw new Error(`资金分配失败: ${allocateResult.error}`);
    }

    this.logger.log(`Wallet allocation completed for expired contract order ${params.sourceOrderNo}`);

    // 3. 保存奖励流水
    await this.rewardLedgerEntryRepository.saveAll(rewards);

    // 4. 更新各系统账户的汇总数据
    const userIds = [...new Set(rewards.map(r => r.userId))];
    for (const userId of userIds) {
      const userRewards = rewards.filter(r => r.userId === userId);
      const accountSequence = userRewards[0].accountSequence;
      const summary = await this.rewardSummaryRepository.getOrCreate(userId, accountSequence);

      for (const reward of userRewards) {
        if (reward.isSettleable) {
          summary.addSettleable(reward.usdtAmount, reward.hashpowerAmount);
        }
      }

      await this.rewardSummaryRepository.save(summary);
    }

    // 5. 发布领域事件
    for (const reward of rewards) {
      await this.eventPublisher.publishAll(reward.domainEvents);
      reward.clearDomainEvents();
    }

    this.logger.log(`Distributed ${rewards.length} rewards to system accounts for expired contract order ${params.sourceOrderNo}`);
  }

  /**
   * 用户认种后，将该用户的待领取奖励转为可结算
   * @deprecated 使用 claimPendingRewardsForAccountSequence 代替
   */
  async claimPendingRewardsForUser(userId: bigint): Promise<{
    claimedCount: number;
    totalUsdtClaimed: number;
  }> {
    this.logger.log(`Claiming pending rewards for user ${userId}`);

    const pendingRewards = await this.rewardLedgerEntryRepository.findPendingByUserId(userId);
    // 使用 userId 作为 accountSequence (系统账户场景)
    const summary = await this.rewardSummaryRepository.getOrCreate(userId, userId.toString());

    let claimedCount = 0;
    let totalUsdtClaimed = 0;

    for (const reward of pendingRewards) {
      if (!reward.isExpiredNow()) {
        reward.claim();
        await this.rewardLedgerEntryRepository.save(reward);

        summary.movePendingToSettleable(reward.usdtAmount, reward.hashpowerAmount);

        claimedCount++;
        totalUsdtClaimed += reward.usdtAmount.amount;

        await this.eventPublisher.publishAll(reward.domainEvents);
        reward.clearDomainEvents();
      }
    }

    await this.rewardSummaryRepository.save(summary);

    this.logger.log(`Claimed ${claimedCount} rewards for user ${userId}, total ${totalUsdtClaimed} USDT`);

    return { claimedCount, totalUsdtClaimed };
  }

  /**
   * 用户认种后，将该用户的待领取奖励转为可结算（使用 accountSequence）
   */
  async claimPendingRewardsForAccountSequence(accountSequence: string): Promise<{
    claimedCount: number;
    totalUsdtClaimed: number;
  }> {
    this.logger.log(`Claiming pending rewards for accountSequence ${accountSequence}`);

    const pendingRewards = await this.rewardLedgerEntryRepository.findPendingByAccountSequence(accountSequence);
    if (pendingRewards.length === 0) {
      this.logger.log(`No pending rewards found for accountSequence ${accountSequence}`);
      return { claimedCount: 0, totalUsdtClaimed: 0 };
    }

    // 从第一条奖励记录获取 userId
    const userId = pendingRewards[0].userId;
    const summary = await this.rewardSummaryRepository.getOrCreate(userId, accountSequence);

    let claimedCount = 0;
    let totalUsdtClaimed = 0;

    for (const reward of pendingRewards) {
      if (!reward.isExpiredNow()) {
        reward.claim();
        await this.rewardLedgerEntryRepository.save(reward);

        summary.movePendingToSettleable(reward.usdtAmount, reward.hashpowerAmount);

        claimedCount++;
        totalUsdtClaimed += reward.usdtAmount.amount;

        await this.eventPublisher.publishAll(reward.domainEvents);
        reward.clearDomainEvents();
      }
    }

    await this.rewardSummaryRepository.save(summary);

    this.logger.log(`Claimed ${claimedCount} rewards for accountSequence ${accountSequence}, total ${totalUsdtClaimed} USDT`);

    return { claimedCount, totalUsdtClaimed };
  }

  /**
   * 结算可结算收益
   */
  async settleRewards(params: {
    accountSequence: string;
    settleCurrency: string; // BNB/OG/USDT/DST
  }): Promise<{
    success: boolean;
    settledUsdtAmount: number;
    receivedAmount: number;
    settleCurrency: string;
    txHash?: string;
    error?: string;
  }> {
    this.logger.log(`Settling rewards for accountSequence ${params.accountSequence}`);

    // 1. 获取可结算奖励
    const settleableRewards = await this.rewardLedgerEntryRepository.findSettleableByAccountSequence(params.accountSequence);

    if (settleableRewards.length === 0) {
      return {
        success: false,
        settledUsdtAmount: 0,
        receivedAmount: 0,
        settleCurrency: params.settleCurrency,
        error: '没有可结算的收益',
      };
    }

    // 2. 计算总金额
    const totalUsdt = settleableRewards.reduce((sum, r) => sum + r.usdtAmount.amount, 0);
    const totalHashpower = settleableRewards.reduce((sum, r) => sum + r.hashpowerAmount.value, 0);

    // 3. 调用钱包服务执行SWAP (使用第一条记录的userId)
    const userId = settleableRewards[0].userId;
    const swapResult = await this.walletService.executeSwap({
      userId: userId,
      usdtAmount: totalUsdt,
      targetCurrency: params.settleCurrency,
    });

    if (!swapResult.success) {
      return {
        success: false,
        settledUsdtAmount: totalUsdt,
        receivedAmount: 0,
        settleCurrency: params.settleCurrency,
        error: swapResult.error,
      };
    }

    // 4. 更新奖励状态为已结算
    for (const reward of settleableRewards) {
      reward.settle(params.settleCurrency, swapResult.receivedAmount!);
      await this.rewardLedgerEntryRepository.save(reward);
      await this.eventPublisher.publishAll(reward.domainEvents);
      reward.clearDomainEvents();
    }

    // 5. 更新汇总数据
    const summary = await this.rewardSummaryRepository.findByAccountSequence(params.accountSequence);
    if (summary) {
      summary.settle(Money.USDT(totalUsdt), Hashpower.create(totalHashpower));
      await this.rewardSummaryRepository.save(summary);

      // 写入 Outbox 同步到 wallet-service
      // [已屏蔽] 前端直接从 reward-service 查询，不再同步到 wallet-service
      // await this.publishSummaryUpdatesToOutbox([summary]);
    }

    this.logger.log(`Settled ${totalUsdt} USDT for accountSequence ${params.accountSequence}`);

    return {
      success: true,
      settledUsdtAmount: totalUsdt,
      receivedAmount: swapResult.receivedAmount!,
      settleCurrency: params.settleCurrency,
      txHash: swapResult.txHash,
    };
  }

  /**
   * 结算到余额 (可结算USDT → 钱包USDT余额，无币种兑换)
   * 将可结算收益直接转入钱包 USDT 余额，并记录详细的来源信息
   */
  async settleRewardsToBalance(accountSequence: string): Promise<{
    success: boolean;
    settlementId?: string;
    settledUsdtAmount: number;
    settledHashpowerAmount: number;
    rewardCount: number;
    breakdown?: Record<string, number>;
    balanceAfter?: number;
    error?: string;
  }> {
    this.logger.log(`Settling rewards to balance for accountSequence ${accountSequence}`);

    // 1. 获取可结算奖励
    const settleableRewards = await this.rewardLedgerEntryRepository.findSettleableByAccountSequence(accountSequence);

    if (settleableRewards.length === 0) {
      return {
        success: false,
        settledUsdtAmount: 0,
        settledHashpowerAmount: 0,
        rewardCount: 0,
        error: '没有可结算的收益',
      };
    }

    // 2. 计算总金额和按权益类型分解
    const totalUsdt = settleableRewards.reduce((sum, r) => sum + r.usdtAmount.amount, 0);
    const totalHashpower = settleableRewards.reduce((sum, r) => sum + r.hashpowerAmount.value, 0);
    const rewardEntryIds = settleableRewards.map(r => r.id?.toString() || '');

    // 按权益类型分解
    const breakdown: Record<string, number> = {};
    for (const reward of settleableRewards) {
      const rightType = reward.rewardSource.rightType;
      breakdown[rightType] = (breakdown[rightType] || 0) + reward.usdtAmount.amount;
    }

    // 3. 构建详细的结算备注（按权益类型分组，列出每笔奖励的来源用户）
    const memoLines = [
      `结算 ${totalUsdt.toFixed(2)} 绿积分到钱包余额`,
      `涉及 ${settleableRewards.length} 笔奖励`,
    ];

    // 按权益类型分组，收集每笔奖励的来源用户和金额
    const rewardsByType: Record<string, Array<{ sourceUser: string; amount: number }>> = {};
    for (const reward of settleableRewards) {
      const rightType = reward.rewardSource.rightType;
      if (!rewardsByType[rightType]) {
        rewardsByType[rightType] = [];
      }
      // 从 memo 中提取来源用户，格式如 "分享权益：来自用户D2512120001的认种"
      let sourceUser = reward.rewardSource.sourceUserId.toString();
      const memoMatch = reward.memo.match(/来自用户([A-Z]\d+)的认种/);
      if (memoMatch) {
        sourceUser = memoMatch[1];
      }
      rewardsByType[rightType].push({
        sourceUser,
        amount: reward.usdtAmount.amount,
      });
    }

    // 输出按权益类型分组的详细信息
    for (const [rightType, rewards] of Object.entries(rewardsByType)) {
      const typeTotal = rewards.reduce((sum, r) => sum + r.amount, 0);
      memoLines.push(`  - ${rightType}: ${typeTotal.toFixed(2)} 绿积分`);
      for (const r of rewards) {
        memoLines.push(`      来自 ${r.sourceUser}: ${r.amount.toFixed(2)} 绿积分`);
      }
    }
    const memo = memoLines.join('\n');

    // 4. 调用钱包服务执行结算
    const walletResult = await this.walletService.settleToBalance({
      accountSequence,
      usdtAmount: totalUsdt,
      rewardEntryIds,
      breakdown,
      memo,
    });

    if (!walletResult.success) {
      return {
        success: false,
        settledUsdtAmount: totalUsdt,
        settledHashpowerAmount: totalHashpower,
        rewardCount: settleableRewards.length,
        error: walletResult.error,
      };
    }

    // 5. 更新奖励状态为已结算
    for (const reward of settleableRewards) {
      reward.settle('USDT', reward.usdtAmount.amount);
      await this.rewardLedgerEntryRepository.save(reward);
      await this.eventPublisher.publishAll(reward.domainEvents);
      reward.clearDomainEvents();
    }

    // 6. 更新汇总数据
    const summary = await this.rewardSummaryRepository.findByAccountSequence(accountSequence);
    if (summary) {
      summary.settle(Money.USDT(totalUsdt), Hashpower.create(totalHashpower));
      await this.rewardSummaryRepository.save(summary);
    }

    this.logger.log(`Settled ${totalUsdt} USDT to balance for accountSequence ${accountSequence}, ${settleableRewards.length} rewards`);

    return {
      success: true,
      settlementId: walletResult.settlementId,
      settledUsdtAmount: totalUsdt,
      settledHashpowerAmount: totalHashpower,
      rewardCount: settleableRewards.length,
      breakdown,
      balanceAfter: walletResult.balanceAfter,
    };
  }

  /**
   * 过期到期的待领取奖励 (定时任务调用)
   */
  async expireOverdueRewards(): Promise<{
    expiredCount: number;
    totalUsdtExpired: number;
  }> {
    this.logger.log('Processing expired rewards');

    const now = new Date();
    const expiredPendingRewards = await this.rewardLedgerEntryRepository.findExpiredPending(now);

    const expiredRewards = this.rewardExpirationService.expireOverdueRewards(expiredPendingRewards);

    let totalUsdtExpired = 0;

    // 按用户分组处理
    const userRewardsMap = new Map<string, RewardLedgerEntry[]>();
    for (const reward of expiredRewards) {
      const userId = reward.userId.toString();
      if (!userRewardsMap.has(userId)) {
        userRewardsMap.set(userId, []);
      }
      userRewardsMap.get(userId)!.push(reward);
      totalUsdtExpired += reward.usdtAmount.amount;
    }

    // 更新每个用户的汇总数据
    const updatedSummaries: RewardSummary[] = [];

    for (const [userId, rewards] of userRewardsMap) {
      const userIdBigInt = BigInt(userId);
      // 使用 userId 作为 accountSequence (过期任务中无法获取真实 accountSequence)
      const summary = await this.rewardSummaryRepository.getOrCreate(userIdBigInt, userId);

      for (const reward of rewards) {
        await this.rewardLedgerEntryRepository.save(reward);
        summary.movePendingToExpired(reward.usdtAmount, reward.hashpowerAmount);
        await this.eventPublisher.publishAll(reward.domainEvents);
        reward.clearDomainEvents();
      }

      await this.rewardSummaryRepository.save(summary);
      updatedSummaries.push(summary);
    }

    // 将过期奖励转入总部社区
    if (expiredRewards.length > 0) {
      const hqSummary = await this.rewardSummaryRepository.getOrCreate(HEADQUARTERS_COMMUNITY_USER_ID, HEADQUARTERS_COMMUNITY_USER_ID.toString());
      const totalHqUsdt = expiredRewards.reduce((sum, r) => sum + r.usdtAmount.amount, 0);
      const totalHqHashpower = expiredRewards.reduce((sum, r) => sum + r.hashpowerAmount.value, 0);
      hqSummary.addSettleable(Money.USDT(totalHqUsdt), Hashpower.create(totalHqHashpower));
      await this.rewardSummaryRepository.save(hqSummary);
      updatedSummaries.push(hqSummary);
    }

    // 写入 Outbox 同步到 wallet-service
    // [已屏蔽] 前端直接从 reward-service 查询，不再同步到 wallet-service
    // if (updatedSummaries.length > 0) {
    //   await this.publishSummaryUpdatesToOutbox(updatedSummaries);
    // }

    this.logger.log(`Expired ${expiredRewards.length} rewards, total ${totalUsdtExpired} USDT`);

    return {
      expiredCount: expiredRewards.length,
      totalUsdtExpired,
    };
  }

  /**
   * 获取用户奖励汇总
   */
  async getRewardSummary(accountSequence: string) {
    const summary = await this.rewardSummaryRepository.findByAccountSequence(accountSequence);

    if (!summary) {
      return {
        pendingUsdt: 0,
        pendingHashpower: 0,
        pendingExpireAt: null,
        settleableUsdt: 0,
        settleableHashpower: 0,
        settledTotalUsdt: 0,
        settledTotalHashpower: 0,
        expiredTotalUsdt: 0,
        expiredTotalHashpower: 0,
      };
    }

    return {
      pendingUsdt: summary.pendingUsdt.amount,
      pendingHashpower: summary.pendingHashpower.value,
      pendingExpireAt: summary.pendingExpireAt,
      settleableUsdt: summary.settleableUsdt.amount,
      settleableHashpower: summary.settleableHashpower.value,
      settledTotalUsdt: summary.settledTotalUsdt.amount,
      settledTotalHashpower: summary.settledTotalHashpower.value,
      expiredTotalUsdt: summary.expiredTotalUsdt.amount,
      expiredTotalHashpower: summary.expiredTotalHashpower.value,
    };
  }

  /**
   * 获取用户奖励明细
   */
  async getRewardDetails(
    accountSequence: string,
    filters?: {
      status?: RewardStatus;
      rightType?: RightType;
      startDate?: Date;
      endDate?: Date;
    },
    pagination?: { page: number; pageSize: number },
  ) {
    const rewards = await this.rewardLedgerEntryRepository.findByAccountSequence(accountSequence, filters, pagination);
    const total = await this.rewardLedgerEntryRepository.countByAccountSequence(accountSequence, filters?.status);

    return {
      data: rewards.map(r => ({
        id: r.id?.toString(),
        rightType: r.rewardSource.rightType,
        usdtAmount: r.usdtAmount.amount,
        hashpowerAmount: r.hashpowerAmount.value,
        rewardStatus: r.rewardStatus,
        createdAt: r.createdAt,
        expireAt: r.expireAt,
        remainingTimeMs: r.getRemainingTimeMs(),
        claimedAt: r.claimedAt,
        settledAt: r.settledAt,
        expiredAt: r.expiredAt,
        memo: r.memo,
      })),
      pagination: {
        page: pagination?.page || 1,
        pageSize: pagination?.pageSize || 20,
        total,
      },
    };
  }

  /**
   * 获取待领取奖励（含倒计时）
   */
  async getPendingRewards(accountSequence: string) {
    const rewards = await this.rewardLedgerEntryRepository.findPendingByAccountSequence(accountSequence);

    return rewards.map(r => ({
      id: r.id?.toString(),
      rightType: r.rewardSource.rightType,
      usdtAmount: r.usdtAmount.amount,
      hashpowerAmount: r.hashpowerAmount.value,
      createdAt: r.createdAt,
      expireAt: r.expireAt,
      remainingTimeMs: r.getRemainingTimeMs(),
      sourceOrderNo: r.rewardSource.sourceOrderNo,
      sourceAccountSequence: r.rewardSource.sourceAccountSequence,
      memo: r.memo,
    }));
  }

  /**
   * 获取可结算奖励列表
   */
  async getSettleableRewards(accountSequence: string) {
    const rewards = await this.rewardLedgerEntryRepository.findSettleableByAccountSequence(accountSequence);

    return rewards.map(r => ({
      id: r.id?.toString(),
      rightType: r.rewardSource.rightType,
      usdtAmount: r.usdtAmount.amount,
      hashpowerAmount: r.hashpowerAmount.value,
      createdAt: r.createdAt,
      claimedAt: r.claimedAt,
      sourceOrderNo: r.rewardSource.sourceOrderNo,
      sourceAccountSequence: r.rewardSource.sourceAccountSequence,
      memo: r.memo,
    }));
  }

  /**
   * 发布汇总更新到 Outbox（同步到 wallet-service）
   */
  private async publishSummaryUpdatesToOutbox(summaries: RewardSummary[]): Promise<void> {
    if (summaries.length === 0) return;

    const outboxEvents: OutboxEventData[] = summaries.map(summary => ({
      eventType: 'reward.summary.updated',
      topic: 'reward.summary.updated',
      key: summary.accountSequence,
      aggregateId: summary.accountSequence,
      aggregateType: 'RewardSummary',
      payload: {
        accountSequence: summary.accountSequence,
        userId: summary.userId.toString(),
        pendingUsdt: summary.pendingUsdt.amount,
        pendingHashpower: summary.pendingHashpower.value,
        pendingExpireAt: summary.pendingExpireAt?.toISOString() || null,
        settleableUsdt: summary.settleableUsdt.amount,
        settleableHashpower: summary.settleableHashpower.value,
        settledTotalUsdt: summary.settledTotalUsdt.amount,
        settledTotalHashpower: summary.settledTotalHashpower.value,
        expiredTotalUsdt: summary.expiredTotalUsdt.amount,
        expiredTotalHashpower: summary.expiredTotalHashpower.value,
      },
    }));

    await this.outboxRepository.saveEvents(outboxEvents);

    this.logger.log(
      `[OUTBOX] Published ${outboxEvents.length} reward.summary.updated events to outbox`,
    );
  }

  /**
   * 批量查询月度收益（内部接口，供 authorization-service 调用）
   *
   * 计算指定月份内进入可结算状态（SETTLEABLE）的收益总额
   * - 分享权益：SHARE_RIGHT
   * - 省团队权益：PROVINCE_TEAM_RIGHT
   * - 市团队权益：CITY_TEAM_RIGHT
   *
   * @param accountSequences 账户序列号列表
   * @param month 月份，格式 YYYY-MM
   * @param rightTypes 可选，过滤权益类型
   */
  async batchGetMonthlyEarnings(
    accountSequences: string[],
    month: string,
    rightTypes?: string[],
  ): Promise<{
    accountSequence: string;
    monthlySettleableUsdt: number;
    monthlyShareUsdt: number;
    monthlyProvinceTeamUsdt: number;
    monthlyCityTeamUsdt: number;
    monthlyTotalUsdt: number;
  }[]> {
    if (accountSequences.length === 0) {
      return [];
    }

    // 解析月份，获取该月的起止时间
    const [year, monthNum] = month.split('-').map(Number);
    const startDate = new Date(year, monthNum - 1, 1); // 月份从0开始
    const endDate = new Date(year, monthNum, 1); // 下个月的第一天

    this.logger.debug(
      `[batchGetMonthlyEarnings] month=${month}, startDate=${startDate.toISOString()}, endDate=${endDate.toISOString()}`,
    );

    const results: {
      accountSequence: string;
      monthlySettleableUsdt: number;
      monthlyShareUsdt: number;
      monthlyProvinceTeamUsdt: number;
      monthlyCityTeamUsdt: number;
      monthlyTotalUsdt: number;
    }[] = [];

    // 批量查询每个账户的月度收益
    for (const accountSequence of accountSequences) {
      let monthlySettleableUsdt = 0;
      let monthlyShareUsdt = 0;
      let monthlyProvinceTeamUsdt = 0;
      let monthlyCityTeamUsdt = 0;

      // 查询可结算状态的收益记录
      // 使用 claimedAt 作为进入可结算状态的时间（用户认种后权益进入可结算）
      const entries = await this.rewardLedgerEntryRepository.findByAccountSequence(
        accountSequence,
        {
          status: RewardStatus.SETTLEABLE,
          startDate,
          endDate,
        },
      );

      for (const entry of entries) {
        const rightType = entry.rewardSource.rightType;
        const amount = entry.usdtAmount.amount;

        // 如果指定了权益类型过滤，则只统计指定类型
        if (rightTypes && rightTypes.length > 0 && !rightTypes.includes(rightType)) {
          continue;
        }

        monthlySettleableUsdt += amount;

        // 按权益类型分类统计
        if (rightType === RightType.SHARE_RIGHT) {
          monthlyShareUsdt += amount;
        } else if (rightType === RightType.PROVINCE_TEAM_RIGHT) {
          monthlyProvinceTeamUsdt += amount;
        } else if (rightType === RightType.CITY_TEAM_RIGHT) {
          monthlyCityTeamUsdt += amount;
        }
      }

      results.push({
        accountSequence,
        monthlySettleableUsdt,
        monthlyShareUsdt,
        monthlyProvinceTeamUsdt,
        monthlyCityTeamUsdt,
        monthlyTotalUsdt: monthlySettleableUsdt,
      });
    }

    return results;
  }

  /**
   * 获取结算历史记录（新增接口）
   */
  async getSettlementHistory(
    accountSequence: string,
    pagination?: { page: number; pageSize: number },
  ): Promise<{
    data: Array<{
      id: string;
      usdtAmount: number;
      hashpowerAmount: number;
      settleCurrency: string;
      receivedAmount: number;
      swapTxHash: string | null;
      swapRate: number | null;
      status: string;
      createdAt: Date;
      completedAt: Date | null;
      rewardEntryCount: number;
    }>;
    pagination: {
      page: number;
      pageSize: number;
      total: number;
    };
  }> {
    const page = pagination?.page || 1;
    const pageSize = pagination?.pageSize || 20;

    const records = await this.settlementRecordRepository.findByAccountSequence(
      accountSequence,
      { page, pageSize },
    );
    const total = await this.settlementRecordRepository.countByAccountSequence(accountSequence);

    return {
      data: records.map(r => ({
        id: r.id,
        usdtAmount: r.usdtAmount,
        hashpowerAmount: r.hashpowerAmount,
        settleCurrency: r.settleCurrency,
        receivedAmount: r.receivedAmount,
        swapTxHash: r.swapTxHash,
        swapRate: r.swapRate,
        status: r.status,
        createdAt: r.createdAt,
        completedAt: r.completedAt,
        rewardEntryCount: r.rewardEntryIds.length,
      })),
      pagination: {
        page,
        pageSize,
        total,
      },
    };
  }

  // =============== 系统账户报表统计方法 ===============
  // [2026-01-04] 新增：用于 reporting-service 聚合系统账户报表数据
  // 回滚方式：删除以下方法和构造函数中的 prisma 注入即可

  // [2026-01-06] 新增：按权益类型统计收益汇总
  // 用于系统账户报表中的：手续费汇总、省团队收益汇总、市团队收益汇总、分享引荐收益汇总、社区收益汇总
  // 回滚方式：删除以下方法即可

  /**
   * 获取按权益类型的收益统计汇总
   * [2026-01-06] 更新：统计所有状态的奖励，包括 PENDING、SETTLEABLE、SETTLED、EXPIRED
   *
   * @param rightType 权益类型
   */
  async getRewardsSummaryByType(rightType: string): Promise<{
    totalAmount: number;
    totalCount: number;
    totalSettleableAmount: number;
    totalSettledAmount: number;
    // [2026-01-06] 新增：全量统计（包含所有状态）
    allStatusTotalAmount: number;
    allStatusTotalCount: number;
    pendingAmount: number;
    pendingCount: number;
    expiredAmount: number;
    expiredCount: number;
    byStatus: Array<{
      status: string;
      amount: number;
      count: number;
    }>;
    byMonth: Array<{
      month: string;
      amount: number;
      count: number;
    }>;
  }> {
    this.logger.log(`[getRewardsSummaryByType] 查询权益类型收益统计: ${rightType}`);

    // [2026-01-06] 新增：查询所有状态的总计
    const allStatusResult = await this.prisma.rewardLedgerEntry.aggregate({
      where: {
        rightType: rightType,
      },
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    // 查询总计（SETTLEABLE + SETTLED 状态）- 有效收益
    const aggregateResult = await this.prisma.rewardLedgerEntry.aggregate({
      where: {
        rightType: rightType,
        rewardStatus: { in: ['SETTLEABLE', 'SETTLED'] },
      },
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    // 查询可结算金额
    const settleableResult = await this.prisma.rewardLedgerEntry.aggregate({
      where: {
        rightType: rightType,
        rewardStatus: 'SETTLEABLE',
      },
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    // 查询已结算金额
    const settledResult = await this.prisma.rewardLedgerEntry.aggregate({
      where: {
        rightType: rightType,
        rewardStatus: 'SETTLED',
      },
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    // [2026-01-06] 新增：查询待领取金额
    const pendingResult = await this.prisma.rewardLedgerEntry.aggregate({
      where: {
        rightType: rightType,
        rewardStatus: 'PENDING',
      },
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    // [2026-01-06] 新增：查询已过期金额
    const expiredResult = await this.prisma.rewardLedgerEntry.aggregate({
      where: {
        rightType: rightType,
        rewardStatus: 'EXPIRED',
      },
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    const allStatusTotalAmount = allStatusResult._sum.usdtAmount
      ? Number(allStatusResult._sum.usdtAmount)
      : 0;
    const allStatusTotalCount = allStatusResult._count.id || 0;
    const totalAmount = aggregateResult._sum.usdtAmount
      ? Number(aggregateResult._sum.usdtAmount)
      : 0;
    const totalCount = aggregateResult._count.id || 0;
    const totalSettleableAmount = settleableResult._sum.usdtAmount
      ? Number(settleableResult._sum.usdtAmount)
      : 0;
    const settleableCount = settleableResult._count.id || 0;
    const totalSettledAmount = settledResult._sum.usdtAmount
      ? Number(settledResult._sum.usdtAmount)
      : 0;
    const settledCount = settledResult._count.id || 0;
    const pendingAmount = pendingResult._sum.usdtAmount
      ? Number(pendingResult._sum.usdtAmount)
      : 0;
    const pendingCount = pendingResult._count.id || 0;
    const expiredAmount = expiredResult._sum.usdtAmount
      ? Number(expiredResult._sum.usdtAmount)
      : 0;
    const expiredCount = expiredResult._count.id || 0;

    // [2026-01-06] 修改：查询按月统计（所有状态）
    const byMonth = await this.prisma.$queryRaw<Array<{
      month: string;
      amount: any;
      count: any;
    }>>`
      SELECT
        TO_CHAR(created_at, 'YYYY-MM') as month,
        SUM(usdt_amount) as amount,
        COUNT(*) as count
      FROM reward_ledger_entries
      WHERE right_type = ${rightType}
      GROUP BY TO_CHAR(created_at, 'YYYY-MM')
      ORDER BY month DESC
      LIMIT 12
    `;

    // [2026-01-06] 新增：按状态分组统计
    const byStatus = [
      { status: 'PENDING', amount: pendingAmount, count: pendingCount },
      { status: 'SETTLEABLE', amount: totalSettleableAmount, count: settleableCount },
      { status: 'SETTLED', amount: totalSettledAmount, count: settledCount },
      { status: 'EXPIRED', amount: expiredAmount, count: expiredCount },
    ];

    return {
      totalAmount,
      totalCount,
      totalSettleableAmount,
      totalSettledAmount,
      allStatusTotalAmount,
      allStatusTotalCount,
      pendingAmount,
      pendingCount,
      expiredAmount,
      expiredCount,
      byStatus,
      byMonth: byMonth.map(row => ({
        month: row.month,
        amount: Number(row.amount) || 0,
        count: Number(row.count) || 0,
      })),
    };
  }

  /**
   * 获取所有收益类型的汇总统计
   * 用于系统账户报表中的各类收益汇总Tab
   */
  async getAllRewardTypeSummaries(): Promise<{
    feeAccountSummary: {
      totalAmount: number;
      totalCount: number;
      breakdown: Array<{ rightType: string; amount: number; count: number }>;
    };
    provinceTeamSummary: {
      totalAmount: number;
      totalCount: number;
      totalSettleableAmount: number;
      totalSettledAmount: number;
      byMonth: Array<{ month: string; amount: number; count: number }>;
    };
    cityTeamSummary: {
      totalAmount: number;
      totalCount: number;
      totalSettleableAmount: number;
      totalSettledAmount: number;
      byMonth: Array<{ month: string; amount: number; count: number }>;
    };
    shareReferralSummary: {
      totalAmount: number;
      totalCount: number;
      totalSettleableAmount: number;
      totalSettledAmount: number;
      byMonth: Array<{ month: string; amount: number; count: number }>;
    };
    communitySummary: {
      totalAmount: number;
      totalCount: number;
      totalSettleableAmount: number;
      totalSettledAmount: number;
      byMonth: Array<{ month: string; amount: number; count: number }>;
    };
  }> {
    this.logger.log('[getAllRewardTypeSummaries] 查询所有收益类型汇总');

    // 并行查询各类收益汇总
    const [
      provinceTeamSummary,
      cityTeamSummary,
      shareReferralSummary,
      communitySummary,
      feeBreakdown,
    ] = await Promise.all([
      this.getRewardsSummaryByType(RightType.PROVINCE_TEAM_RIGHT),
      this.getRewardsSummaryByType(RightType.CITY_TEAM_RIGHT),
      this.getRewardsSummaryByType(RightType.SHARE_RIGHT),
      this.getRewardsSummaryByType(RightType.COMMUNITY_RIGHT),
      // 手续费汇总：包括系统费用类型
      this.getFeeAccountSummary(),
    ]);

    return {
      feeAccountSummary: feeBreakdown,
      provinceTeamSummary,
      cityTeamSummary,
      shareReferralSummary,
      communitySummary,
    };
  }

  /**
   * 获取手续费账户汇总（系统费用类型）
   * 包括：成本费、运营费、总部社区基础费、RWAD底池注入
   */
  private async getFeeAccountSummary(): Promise<{
    totalAmount: number;
    totalCount: number;
    breakdown: Array<{ rightType: string; amount: number; count: number }>;
  }> {
    const feeTypes = [
      RightType.COST_FEE,
      RightType.OPERATION_FEE,
      RightType.HEADQUARTERS_BASE_FEE,
      RightType.RWAD_POOL_INJECTION,
    ];

    // 使用 Prisma 的 groupBy 查询各手续费类型的汇总
    const groupedResults = await this.prisma.rewardLedgerEntry.groupBy({
      by: ['rightType'],
      where: {
        rightType: { in: feeTypes },
        rewardStatus: { in: ['SETTLEABLE', 'SETTLED'] },
      },
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    let totalAmount = 0;
    let totalCount = 0;
    const formattedBreakdown = groupedResults.map(row => {
      const amount = Number(row._sum.usdtAmount) || 0;
      const count = Number(row._count.id) || 0;
      totalAmount += amount;
      totalCount += count;
      return {
        rightType: row.rightType,
        amount,
        count,
      };
    });

    return {
      totalAmount,
      totalCount,
      breakdown: formattedBreakdown,
    };
  }

  /**
   * 获取过期收益统计汇总
   * 用于系统账户报表展示过期收益总额
   *
   * 统计 reward_status = 'EXPIRED' 的奖励流水
   */
  async getExpiredRewardsSummary(params: {
    startDate?: Date;
    endDate?: Date;
  }): Promise<{
    totalAmount: number;
    totalCount: number;
    byMonth: Array<{
      month: string;
      amount: number;
      count: number;
    }>;
    byRightType: Array<{
      rightType: string;
      amount: number;
      count: number;
    }>;
  }> {
    this.logger.log(`[getExpiredRewardsSummary] 查询过期收益统计`);

    // 构建日期筛选条件
    const whereClause: any = {
      rewardStatus: 'EXPIRED',
    };
    if (params.startDate || params.endDate) {
      whereClause.expiredAt = {};
      if (params.startDate) {
        whereClause.expiredAt.gte = params.startDate;
      }
      if (params.endDate) {
        whereClause.expiredAt.lte = params.endDate;
      }
    }

    // 查询总计
    const aggregateResult = await this.prisma.rewardLedgerEntry.aggregate({
      where: whereClause,
      _sum: {
        usdtAmount: true,
      },
      _count: {
        id: true,
      },
    });

    const totalAmount = aggregateResult._sum.usdtAmount
      ? Number(aggregateResult._sum.usdtAmount)
      : 0;
    const totalCount = aggregateResult._count.id || 0;

    // 查询按月统计
    const byMonth = await this.prisma.$queryRaw<Array<{
      month: string;
      amount: any;
      count: any;
    }>>`
      SELECT
        TO_CHAR(expired_at, 'YYYY-MM') as month,
        SUM(usdt_amount) as amount,
        COUNT(*) as count
      FROM reward_ledger_entries
      WHERE reward_status = 'EXPIRED'
        AND expired_at IS NOT NULL
      GROUP BY TO_CHAR(expired_at, 'YYYY-MM')
      ORDER BY month DESC
      LIMIT 12
    `;

    // 查询按权益类型统计
    const byRightType = await this.prisma.$queryRaw<Array<{
      rightType: string;
      amount: any;
      count: any;
    }>>`
      SELECT
        right_type as "rightType",
        SUM(usdt_amount) as amount,
        COUNT(*) as count
      FROM reward_ledger_entries
      WHERE reward_status = 'EXPIRED'
      GROUP BY right_type
      ORDER BY amount DESC
    `;

    return {
      totalAmount,
      totalCount,
      byMonth: byMonth.map(row => ({
        month: row.month,
        amount: Number(row.amount) || 0,
        count: Number(row.count) || 0,
      })),
      byRightType: byRightType.map(row => ({
        rightType: row.rightType,
        amount: Number(row.amount) || 0,
        count: Number(row.count) || 0,
      })),
    };
  }

  // [2026-01-06] 新增：获取收益类型的详细记录列表
  // 用于系统账户报表中展示各收益类型的明细
  // 回滚方式：删除以下方法即可
  /**
   * 获取指定收益类型的详细记录列表
   * @param rightType 权益类型
   * @param page 页码
   * @param pageSize 每页条数
   */
  async getRewardEntriesByType(params: {
    rightType: string;
    page?: number;
    pageSize?: number;
  }): Promise<{
    entries: Array<{
      id: string;
      accountSequence: string;
      sourceAccountSequence: string | null;  // [2026-02-05] 新增：来源用户账户序列号
      sourceOrderId: string;
      rightType: string;
      rewardStatus: string;
      usdtAmount: number;
      hashpowerAmount: number;
      createdAt: string;
      claimedAt: string | null;
      expiredAt: string | null;
    }>;
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
  }> {
    const page = params.page ?? 1;
    const pageSize = params.pageSize ?? 50;
    const skip = (page - 1) * pageSize;

    this.logger.log(`[getRewardEntriesByType] 查询权益类型详细记录: ${params.rightType}, page=${page}, pageSize=${pageSize}`);

    // 查询总数
    const total = await this.prisma.rewardLedgerEntry.count({
      where: {
        rightType: params.rightType,
        rewardStatus: { in: ['SETTLEABLE', 'SETTLED'] },
      },
    });

    // 查询数据
    const entries = await this.prisma.rewardLedgerEntry.findMany({
      where: {
        rightType: params.rightType,
        rewardStatus: { in: ['SETTLEABLE', 'SETTLED'] },
      },
      orderBy: { createdAt: 'desc' },
      skip,
      take: pageSize,
    });

    return {
      entries: entries.map(entry => ({
        id: entry.id.toString(),
        accountSequence: entry.accountSequence,
        // [2026-02-05] 新增：返回来源用户的账户序列号
        sourceAccountSequence: entry.sourceAccountSequence ?? null,
        sourceOrderId: entry.sourceOrderNo,
        rightType: entry.rightType,
        rewardStatus: entry.rewardStatus,
        usdtAmount: Number(entry.usdtAmount),
        hashpowerAmount: Number(entry.hashpowerAmount),
        createdAt: entry.createdAt.toISOString(),
        claimedAt: entry.claimedAt?.toISOString() ?? null,
        expiredAt: entry.expiredAt?.toISOString() ?? null,
      })),
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize),
    };
  }

  /**
   * 获取手续费类型的详细记录列表
   * @param page 页码
   * @param pageSize 每页条数
   */
  async getFeeEntriesDetailed(params: {
    page?: number;
    pageSize?: number;
  }): Promise<{
    entries: Array<{
      id: string;
      accountSequence: string;
      sourceOrderId: string;
      rightType: string;
      rewardStatus: string;
      usdtAmount: number;
      hashpowerAmount: number;
      createdAt: string;
      claimedAt: string | null;
      expiredAt: string | null;
    }>;
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
  }> {
    const page = params.page ?? 1;
    const pageSize = params.pageSize ?? 50;
    const skip = (page - 1) * pageSize;
    const feeTypes = [
      RightType.COST_FEE,
      RightType.OPERATION_FEE,
      RightType.HEADQUARTERS_BASE_FEE,
      RightType.RWAD_POOL_INJECTION,
    ];

    this.logger.log(`[getFeeEntriesDetailed] 查询手续费类型详细记录, page=${page}, pageSize=${pageSize}`);

    // 查询总数
    const total = await this.prisma.rewardLedgerEntry.count({
      where: {
        rightType: { in: feeTypes },
        rewardStatus: { in: ['SETTLEABLE', 'SETTLED'] },
      },
    });

    // 查询数据
    const entries = await this.prisma.rewardLedgerEntry.findMany({
      where: {
        rightType: { in: feeTypes },
        rewardStatus: { in: ['SETTLEABLE', 'SETTLED'] },
      },
      orderBy: { createdAt: 'desc' },
      skip,
      take: pageSize,
    });

    return {
      entries: entries.map(entry => ({
        id: entry.id.toString(),
        accountSequence: entry.accountSequence,
        sourceOrderId: entry.sourceOrderNo,
        rightType: entry.rightType,
        rewardStatus: entry.rewardStatus,
        usdtAmount: Number(entry.usdtAmount),
        hashpowerAmount: Number(entry.hashpowerAmount),
        createdAt: entry.createdAt.toISOString(),
        claimedAt: entry.claimedAt?.toISOString() ?? null,
        expiredAt: entry.expiredAt?.toISOString() ?? null,
      })),
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize),
    };
  }

  // [2026-01-07] 新增：获取过期收益明细列表
  // 用于系统账户报表中展示过期收益的具体记录
  // 回滚方式：删除以下方法即可
  /**
   * 获取过期收益明细列表
   * @param page 页码
   * @param pageSize 每页条数
   * @param rightType 可选的权益类型筛选
   */
  async getExpiredRewardsEntries(params: {
    page?: number;
    pageSize?: number;
    rightType?: string;
  }): Promise<{
    entries: Array<{
      id: string;
      accountSequence: string;
      userId: number;
      sourceOrderId: string;
      rightType: string;
      usdtAmount: number;
      hashpowerAmount: number;
      createdAt: string;
      expiredAt: string | null;
    }>;
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
  }> {
    const page = params.page ?? 1;
    const pageSize = params.pageSize ?? 50;
    const skip = (page - 1) * pageSize;

    this.logger.log(`[getExpiredRewardsEntries] 查询过期收益明细, page=${page}, pageSize=${pageSize}, rightType=${params.rightType || 'all'}`);

    // 构建查询条件
    const whereClause: any = {
      rewardStatus: 'EXPIRED',
    };
    if (params.rightType) {
      whereClause.rightType = params.rightType;
    }

    // 查询总数
    const total = await this.prisma.rewardLedgerEntry.count({
      where: whereClause,
    });

    // 查询数据
    const entries = await this.prisma.rewardLedgerEntry.findMany({
      where: whereClause,
      orderBy: { expiredAt: 'desc' },
      skip,
      take: pageSize,
    });

    return {
      entries: entries.map(entry => ({
        id: entry.id.toString(),
        accountSequence: entry.accountSequence,
        userId: Number(entry.userId),
        sourceOrderId: entry.sourceOrderNo,
        rightType: entry.rightType,
        usdtAmount: Number(entry.usdtAmount),
        hashpowerAmount: Number(entry.hashpowerAmount),
        createdAt: entry.createdAt.toISOString(),
        expiredAt: entry.expiredAt?.toISOString() ?? null,
      })),
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize),
    };
  }
}
