import { Controller, Get, Post, Body, Query, Param, HttpException, HttpStatus } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBody, ApiQuery, ApiParam } from '@nestjs/swagger';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { NetworkSyncService } from '../../application/services/network-sync.service';
import { ManualMiningService } from '../../application/services/manual-mining.service';
import { BatchMiningService, BatchMiningItem, BatchMiningRequest } from '../../application/services/batch-mining.service';
import { Public } from '../../shared/guards/jwt-auth.guard';

@ApiTags('Admin')
@Controller('mining/admin')
export class AdminController {
  constructor(
    private readonly prisma: PrismaService,
    private readonly networkSyncService: NetworkSyncService,
    private readonly configService: ConfigService,
    private readonly manualMiningService: ManualMiningService,
    private readonly batchMiningService: BatchMiningService,
  ) {}

  @Get('accounts/sync')
  @Public()
  @ApiOperation({ summary: '获取所有挖矿账户用于同步' })
  async getAllAccountsForSync() {
    const accounts = await this.prisma.miningAccount.findMany({
      select: {
        accountSequence: true,
        totalMined: true,
        availableBalance: true,
        frozenBalance: true,
        totalContribution: true,
        createdAt: true,
        updatedAt: true,
      },
    });

    return {
      accounts: accounts.map((acc) => ({
        accountSequence: acc.accountSequence,
        totalMined: acc.totalMined.toString(),
        availableBalance: acc.availableBalance.toString(),
        frozenBalance: acc.frozenBalance.toString(),
        totalContribution: acc.totalContribution.toString(),
        createdAt: acc.createdAt,
        updatedAt: acc.updatedAt,
      })),
      total: accounts.length,
    };
  }

  @Get('status')
  @Public()
  @ApiOperation({ summary: '获取挖矿系统状态' })
  async getStatus() {
    const config = await this.prisma.miningConfig.findFirst();
    const accountCount = await this.prisma.miningAccount.count();

    // 用户挖矿账户统计
    const userMiningStats = await this.prisma.miningAccount.aggregate({
      _sum: {
        totalContribution: true,
        totalMined: true,
      },
    });

    // 系统账户算力
    const systemContribution = await this.prisma.systemMiningAccount.aggregate({
      _sum: { totalContribution: true },
    });

    // 待解锁算力
    const pendingContribution = await this.prisma.pendingContributionMining.aggregate({
      _sum: { amount: true },
      where: { isExpired: false },
    });

    return {
      initialized: !!config,
      isActive: config?.isActive || false,
      activatedAt: config?.activatedAt,
      currentEra: config?.currentEra || 0,
      distributionPool: config?.distributionPool?.toString() || '0',
      remainingDistribution: config?.remainingDistribution?.toString() || '0',
      secondDistribution: config?.secondDistribution?.toString() || '0',
      accountCount,
      // 用户有效算力
      totalContribution: userMiningStats._sum.totalContribution?.toString() || '0',
      // 已分配积分股（所有用户的 totalMined 总和）
      totalDistributed: userMiningStats._sum.totalMined?.toString() || '0',
      // 全网理论算力（从 contribution-service 同步）
      networkTotalContribution: config?.networkTotalContribution?.toString() || '0',
      totalTreeCount: config?.totalTreeCount || 0,
      contributionPerTree: config?.contributionPerTree?.toString() || '22617',
      networkLastSyncedAt: config?.networkLastSyncedAt,
      // 系统账户算力
      systemContribution: systemContribution._sum.totalContribution?.toString() || '0',
      // 待解锁算力
      pendingContribution: pendingContribution._sum.amount?.toString() || '0',
    };
  }

  @Post('activate')
  @Public()
  @ApiOperation({ summary: '激活挖矿系统' })
  async activate() {
    const config = await this.prisma.miningConfig.findFirst();

    if (!config) {
      throw new HttpException('挖矿系统未初始化，请先运行 seed 脚本', HttpStatus.BAD_REQUEST);
    }

    if (config.isActive) {
      return { success: true, message: '挖矿系统已经处于激活状态' };
    }

    await this.prisma.miningConfig.update({
      where: { id: config.id },
      data: {
        isActive: true,
        activatedAt: new Date(),
      },
    });

    return { success: true, message: '挖矿系统已激活' };
  }

  @Post('deactivate')
  @Public()
  @ApiOperation({ summary: '停用挖矿系统' })
  async deactivate() {
    const config = await this.prisma.miningConfig.findFirst();

    if (!config) {
      throw new HttpException('挖矿系统未初始化', HttpStatus.BAD_REQUEST);
    }

    if (!config.isActive) {
      return { success: true, message: '挖矿系统已经处于停用状态' };
    }

    await this.prisma.miningConfig.update({
      where: { id: config.id },
      data: {
        isActive: false,
      },
    });

    return { success: true, message: '挖矿系统已停用' };
  }

  @Post('sync-network')
  @Public()
  @ApiOperation({ summary: '从 contribution-service 同步全网数据（系统账户、全网进度）' })
  async syncNetwork() {
    const contributionServiceUrl = this.configService.get<string>(
      'CONTRIBUTION_SERVICE_URL',
      'http://localhost:3020',
    );

    return this.networkSyncService.syncFromContributionService(contributionServiceUrl);
  }

  @Get('system-accounts')
  @Public()
  @ApiOperation({ summary: '获取系统账户挖矿状态' })
  async getSystemAccounts() {
    const accounts = await this.prisma.systemMiningAccount.findMany({
      orderBy: [{ accountType: 'asc' }, { regionCode: 'asc' }],
    });

    return {
      accounts: accounts.map((acc) => ({
        id: acc.id,
        accountType: acc.accountType,
        regionCode: acc.regionCode,
        name: acc.name,
        totalMined: acc.totalMined.toString(),
        availableBalance: acc.availableBalance.toString(),
        totalContribution: acc.totalContribution.toString(),
        lastSyncedAt: acc.lastSyncedAt,
      })),
      total: accounts.length,
    };
  }

  @Get('system-accounts/:accountType/records')
  @Public()
  @ApiOperation({ summary: '获取系统账户挖矿记录' })
  @ApiParam({ name: 'accountType', type: String, description: '系统账户类型（OPERATION/PROVINCE/CITY/HEADQUARTERS）' })
  @ApiQuery({ name: 'regionCode', required: false, type: String, description: '区域代码（省/市代码）' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  async getSystemAccountMiningRecords(
    @Param('accountType') accountType: string,
    @Query('regionCode') regionCode?: string,
    @Query('page') page?: number,
    @Query('pageSize') pageSize?: number,
  ) {
    const pageNum = page ?? 1;
    const pageSizeNum = pageSize ?? 20;
    const skip = (pageNum - 1) * pageSizeNum;

    // 先通过 accountType + regionCode 查找系统账户
    // 使用 findFirst 替代 findUnique，因为 regionCode 可以为 null
    const regionCodeValue = regionCode || null;
    const account = await this.prisma.systemMiningAccount.findFirst({
      where: {
        accountType,
        regionCode: regionCodeValue === null ? { equals: null } : regionCodeValue,
      },
    });

    if (!account) {
      return {
        records: [],
        total: 0,
        page: pageNum,
        pageSize: pageSizeNum,
        accountType,
        regionCode: regionCodeValue,
      };
    }

    const [records, total] = await Promise.all([
      this.prisma.systemMiningRecord.findMany({
        where: { systemAccountId: account.id },
        orderBy: { miningMinute: 'desc' },
        skip,
        take: pageSizeNum,
      }),
      this.prisma.systemMiningRecord.count({
        where: { systemAccountId: account.id },
      }),
    ]);

    return {
      records: records.map((record) => ({
        id: record.id,
        accountType,
        regionCode: regionCode || null,
        miningMinute: record.miningMinute,
        contributionRatio: record.contributionRatio.toString(),
        totalContribution: record.totalContribution.toString(),
        secondDistribution: record.secondDistribution.toString(),
        minedAmount: record.minedAmount.toString(),
        createdAt: record.createdAt,
      })),
      total,
      page: pageNum,
      pageSize: pageSizeNum,
      accountType,
      regionCode: regionCodeValue,
    };
  }

  @Get('system-accounts/:accountType/transactions')
  @Public()
  @ApiOperation({ summary: '获取系统账户交易记录' })
  @ApiParam({ name: 'accountType', type: String, description: '系统账户类型（OPERATION/PROVINCE/CITY/HEADQUARTERS）' })
  @ApiQuery({ name: 'regionCode', required: false, type: String, description: '区域代码（省/市代码）' })
  @ApiQuery({ name: 'referenceType', required: false, type: String, description: '关联类型筛选（如 BATCH_MINING）' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  async getSystemAccountTransactions(
    @Param('accountType') accountType: string,
    @Query('regionCode') regionCode?: string,
    @Query('referenceType') referenceType?: string,
    @Query('page') page?: number,
    @Query('pageSize') pageSize?: number,
  ) {
    const pageNum = page ?? 1;
    const pageSizeNum = pageSize ?? 20;
    const skip = (pageNum - 1) * pageSizeNum;

    // 先通过 accountType + regionCode 查找系统账户
    // 使用 findFirst 替代 findUnique，因为 regionCode 可以为 null
    const regionCodeValue = regionCode || null;
    const account = await this.prisma.systemMiningAccount.findFirst({
      where: {
        accountType,
        regionCode: regionCodeValue === null ? { equals: null } : regionCodeValue,
      },
    });

    if (!account) {
      return {
        transactions: [],
        total: 0,
        page: pageNum,
        pageSize: pageSizeNum,
        accountType,
        regionCode: regionCodeValue,
      };
    }

    const where: any = { systemAccountId: account.id };
    if (referenceType) {
      where.referenceType = referenceType;
    }

    const [transactions, total] = await Promise.all([
      this.prisma.systemMiningTransaction.findMany({
        where,
        orderBy: { createdAt: 'desc' },
        skip,
        take: pageSizeNum,
      }),
      this.prisma.systemMiningTransaction.count({ where }),
    ]);

    return {
      transactions: transactions.map((tx) => ({
        id: tx.id,
        accountType,
        regionCode: regionCodeValue,
        type: tx.type,
        amount: tx.amount.toString(),
        balanceBefore: tx.balanceBefore.toString(),
        balanceAfter: tx.balanceAfter.toString(),
        referenceId: tx.referenceId,
        referenceType: tx.referenceType,
        memo: tx.memo,
        createdAt: tx.createdAt,
      })),
      total,
      page: pageNum,
      pageSize: pageSizeNum,
      accountType,
      regionCode: regionCodeValue,
    };
  }

  @Get('mining/status')
  @Public()
  @ApiOperation({ summary: '获取挖矿进度状态（类似销毁进度）' })
  async getMiningStatus() {
    const config = await this.prisma.miningConfig.findFirst();

    if (!config) {
      return {
        totalDistributed: '0',
        distributionPool: '0',
        remainingDistribution: '0',
        miningProgress: '0',
        minuteDistribution: '0',
        remainingMinutes: 0,
        lastMiningMinute: null,
        isActive: false,
        currentEra: 0,
      };
    }

    // 获取用户已分配总量
    const userMiningStats = await this.prisma.miningAccount.aggregate({
      _sum: { totalMined: true },
    });

    // 获取系统账户已分配总量
    const systemMiningStats = await this.prisma.systemMiningAccount.aggregate({
      _sum: { totalMined: true },
    });

    // 总分配量 = 用户分配 + 系统账户分配
    const userDistributed = userMiningStats._sum.totalMined || 0;
    const systemDistributed = systemMiningStats._sum.totalMined || 0;
    const totalDistributedDecimal = Number(userDistributed) + Number(systemDistributed);

    // 获取最后分配时间（从分钟统计表查询）
    const lastMinuteStat = await this.prisma.minuteMiningStat.findFirst({
      orderBy: { minute: 'desc' },
      select: { minute: true },
    });

    // 计算每分钟分配量 (秒分配量 * 60)
    const secondDistribution = Number(config.secondDistribution || 0);
    const minuteDistribution = secondDistribution * 60;

    // 计算剩余分配量
    const distributionPool = Number(config.distributionPool || 0);
    const remainingDistribution = Number(config.remainingDistribution || 0);

    // 计算进度百分比
    const distributed = distributionPool - remainingDistribution;
    const miningProgress = distributionPool > 0
      ? (distributed / distributionPool) * 100
      : 0;

    // 计算剩余分钟数
    const remainingMinutes = minuteDistribution > 0
      ? Math.ceil(remainingDistribution / minuteDistribution)
      : 0;

    return {
      totalDistributed: totalDistributedDecimal.toFixed(8),
      distributionPool: distributionPool.toFixed(8),
      remainingDistribution: remainingDistribution.toFixed(8),
      miningProgress: miningProgress.toFixed(4),
      minuteDistribution: minuteDistribution.toFixed(8),
      remainingMinutes,
      lastMiningMinute: lastMinuteStat?.minute || null,
      isActive: config.isActive,
      currentEra: config.currentEra,
    };
  }

  // ==================== 手工补发挖矿 ====================

  @Post('manual-mining/calculate')
  @Public()
  @ApiOperation({ summary: '计算手工补发挖矿预估金额' })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['accountSequence', 'adoptionDate'],
      properties: {
        accountSequence: { type: 'string', description: '用户账户序列号' },
        adoptionDate: { type: 'string', format: 'date', description: '认种日期 (YYYY-MM-DD)' },
      },
    },
  })
  async calculateManualMining(@Body() body: { accountSequence: string; adoptionDate: string }) {
    return this.manualMiningService.calculate(body);
  }

  @Post('manual-mining/execute')
  @Public()
  @ApiOperation({ summary: '执行手工补发挖矿' })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['accountSequence', 'adoptionDate', 'operatorId', 'operatorName', 'reason'],
      properties: {
        accountSequence: { type: 'string', description: '用户账户序列号' },
        adoptionDate: { type: 'string', format: 'date', description: '认种日期 (YYYY-MM-DD)' },
        operatorId: { type: 'string', description: '操作管理员ID' },
        operatorName: { type: 'string', description: '操作管理员名称' },
        reason: { type: 'string', description: '补发原因（必填）' },
      },
    },
  })
  async executeManualMining(
    @Body() body: {
      accountSequence: string;
      adoptionDate: string;
      operatorId: string;
      operatorName: string;
      reason: string;
    },
  ) {
    return this.manualMiningService.execute(body);
  }

  @Get('manual-mining/records')
  @Public()
  @ApiOperation({ summary: '获取手工补发记录列表' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  async getManualMiningRecords(
    @Query('page') page?: number,
    @Query('pageSize') pageSize?: number,
  ) {
    return this.manualMiningService.listRecords(page ?? 1, pageSize ?? 20);
  }

  @Get('manual-mining/records/:accountSequence')
  @Public()
  @ApiOperation({ summary: '查询指定用户的手工补发记录' })
  @ApiParam({ name: 'accountSequence', type: String })
  async getManualMiningRecordByAccount(@Param('accountSequence') accountSequence: string) {
    const record = await this.manualMiningService.getRecordByAccountSequence(accountSequence);
    if (!record) {
      throw new HttpException('该用户没有手工补发记录', HttpStatus.NOT_FOUND);
    }
    return record;
  }

  @Post('manual-mining/mark-synced/:recordId')
  @Public()
  @ApiOperation({ summary: '标记手工补发记录钱包已同步（内部调用）' })
  @ApiParam({ name: 'recordId', type: String })
  async markManualMiningSynced(@Param('recordId') recordId: string) {
    await this.manualMiningService.markWalletSynced(recordId);
    return { success: true, message: '已标记为同步完成' };
  }

  // ==================== 待解锁算力（Pending Contributions）====================

  @Get('pending-contributions')
  @Public()
  @ApiOperation({ summary: '获取待解锁算力列表' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  @ApiQuery({ name: 'contributionType', required: false, type: String, description: '算力类型筛选' })
  async getPendingContributions(
    @Query('page') page?: number,
    @Query('pageSize') pageSize?: number,
    @Query('contributionType') contributionType?: string,
  ) {
    const pageNum = page ?? 1;
    const pageSizeNum = pageSize ?? 20;
    const skip = (pageNum - 1) * pageSizeNum;

    const where: any = { isExpired: false };
    if (contributionType) {
      where.contributionType = contributionType;
    }

    const [contributions, total] = await Promise.all([
      this.prisma.pendingContributionMining.findMany({
        where,
        orderBy: { createdAt: 'desc' },
        skip,
        take: pageSizeNum,
      }),
      this.prisma.pendingContributionMining.count({ where }),
    ]);

    return {
      contributions: contributions.map((c) => ({
        id: c.id.toString(),
        sourceAdoptionId: c.sourceAdoptionId.toString(),
        sourceAccountSequence: c.sourceAccountSequence,
        wouldBeAccountSequence: c.wouldBeAccountSequence,
        contributionType: c.contributionType,
        amount: c.amount.toString(),
        reason: c.reason,
        effectiveDate: c.effectiveDate,
        expireDate: c.expireDate,
        isExpired: c.isExpired,
        lastSyncedAt: c.lastSyncedAt,
        createdAt: c.createdAt,
      })),
      total,
      page: pageNum,
      pageSize: pageSizeNum,
    };
  }

  @Get('pending-contributions/summary')
  @Public()
  @ApiOperation({ summary: '获取待解锁算力汇总统计' })
  async getPendingContributionsSummary() {
    // 按类型分组统计
    const byType = await this.prisma.pendingContributionMining.groupBy({
      by: ['contributionType'],
      where: { isExpired: false },
      _sum: { amount: true },
      _count: { id: true },
    });

    // 总计
    const total = await this.prisma.pendingContributionMining.aggregate({
      where: { isExpired: false },
      _sum: { amount: true },
      _count: { id: true },
    });

    // 总挖矿收益（归总部）
    const totalMined = await this.prisma.pendingMiningRecord.aggregate({
      _sum: { minedAmount: true },
    });

    return {
      byType: byType.map((t) => ({
        contributionType: t.contributionType,
        totalAmount: t._sum.amount?.toString() || '0',
        count: t._count.id,
      })),
      total: {
        totalAmount: total._sum.amount?.toString() || '0',
        count: total._count.id,
      },
      totalMinedToHeadquarters: totalMined._sum.minedAmount?.toString() || '0',
    };
  }

  @Get('pending-contributions/:id/records')
  @Public()
  @ApiOperation({ summary: '获取某条待解锁算力的挖矿记录' })
  @ApiParam({ name: 'id', type: String, description: '待解锁算力ID' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  async getPendingContributionMiningRecords(
    @Param('id') id: string,
    @Query('page') page?: number,
    @Query('pageSize') pageSize?: number,
  ) {
    const pageNum = page ?? 1;
    const pageSizeNum = pageSize ?? 20;
    const skip = (pageNum - 1) * pageSizeNum;
    const pendingId = BigInt(id);

    // 获取待解锁算力信息
    const pending = await this.prisma.pendingContributionMining.findUnique({
      where: { id: pendingId },
    });

    if (!pending) {
      throw new HttpException('待解锁算力记录不存在', HttpStatus.NOT_FOUND);
    }

    const [records, total] = await Promise.all([
      this.prisma.pendingMiningRecord.findMany({
        where: { pendingContributionId: pendingId },
        orderBy: { miningMinute: 'desc' },
        skip,
        take: pageSizeNum,
      }),
      this.prisma.pendingMiningRecord.count({
        where: { pendingContributionId: pendingId },
      }),
    ]);

    return {
      pendingContribution: {
        id: pending.id.toString(),
        sourceAdoptionId: pending.sourceAdoptionId.toString(),
        sourceAccountSequence: pending.sourceAccountSequence,
        wouldBeAccountSequence: pending.wouldBeAccountSequence,
        contributionType: pending.contributionType,
        amount: pending.amount.toString(),
        reason: pending.reason,
      },
      records: records.map((r) => ({
        id: r.id.toString(),
        miningMinute: r.miningMinute,
        contributionAmount: r.contributionAmount.toString(),
        networkTotalContribution: r.networkTotalContribution.toString(),
        contributionRatio: r.contributionRatio.toString(),
        secondDistribution: r.secondDistribution.toString(),
        minedAmount: r.minedAmount.toString(),
        allocatedTo: r.allocatedTo,
        createdAt: r.createdAt,
      })),
      total,
      page: pageNum,
      pageSize: pageSizeNum,
    };
  }

  @Get('pending-contributions/mining-records')
  @Public()
  @ApiOperation({ summary: '获取所有待解锁算力的挖矿记录（汇总视图）' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  async getAllPendingMiningRecords(
    @Query('page') page?: number,
    @Query('pageSize') pageSize?: number,
  ) {
    const pageNum = page ?? 1;
    const pageSizeNum = pageSize ?? 20;
    const skip = (pageNum - 1) * pageSizeNum;

    const [records, total] = await Promise.all([
      this.prisma.pendingMiningRecord.findMany({
        orderBy: { miningMinute: 'desc' },
        skip,
        take: pageSizeNum,
        include: {
          pendingContribution: {
            select: {
              contributionType: true,
              wouldBeAccountSequence: true,
              reason: true,
            },
          },
        },
      }),
      this.prisma.pendingMiningRecord.count(),
    ]);

    return {
      records: records.map((r) => ({
        id: r.id.toString(),
        pendingContributionId: r.pendingContributionId.toString(),
        miningMinute: r.miningMinute,
        sourceAccountSequence: r.sourceAccountSequence,
        wouldBeAccountSequence: r.wouldBeAccountSequence,
        contributionType: r.contributionType,
        contributionAmount: r.contributionAmount.toString(),
        networkTotalContribution: r.networkTotalContribution.toString(),
        contributionRatio: r.contributionRatio.toString(),
        secondDistribution: r.secondDistribution.toString(),
        minedAmount: r.minedAmount.toString(),
        allocatedTo: r.allocatedTo,
        reason: r.pendingContribution?.reason,
        createdAt: r.createdAt,
      })),
      total,
      page: pageNum,
      pageSize: pageSizeNum,
    };
  }

  // ==================== 批量补发挖矿 ====================

  @Get('batch-mining/status')
  @Public()
  @ApiOperation({ summary: '获取批量补发状态（是否已执行）' })
  async getBatchMiningStatus() {
    const hasExecuted = await this.batchMiningService.hasExecuted();
    const execution = hasExecuted ? await this.batchMiningService.getExecution() : null;

    return {
      hasExecuted,
      execution,
    };
  }

  @Post('batch-mining/preview')
  @Public()
  @ApiOperation({ summary: '预览批量补发（计算但不执行）' })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['items'],
      properties: {
        items: {
          type: 'array',
          items: {
            type: 'object',
            required: ['accountSequence', 'treeCount', 'miningStartDate', 'batch', 'preMineDays'],
            properties: {
              accountSequence: { type: 'string', description: '注册ID（用户账号序列号）' },
              treeCount: { type: 'number', description: '认种量（棵）' },
              miningStartDate: { type: 'string', description: '挖矿开始时间' },
              batch: { type: 'number', description: '批次号' },
              preMineDays: { type: 'number', description: '授权提前挖的天数' },
              remark: { type: 'string', description: '备注' },
            },
          },
        },
      },
    },
  })
  async previewBatchMining(@Body() body: { items: BatchMiningItem[] }) {
    return this.batchMiningService.preview(body.items);
  }

  @Post('batch-mining/execute')
  @Public()
  @ApiOperation({ summary: '执行批量补发（只能执行一次）' })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['items', 'operatorId', 'operatorName', 'reason'],
      properties: {
        items: {
          type: 'array',
          items: {
            type: 'object',
            required: ['accountSequence', 'treeCount', 'miningStartDate', 'batch', 'preMineDays'],
            properties: {
              accountSequence: { type: 'string', description: '注册ID（用户账号序列号）' },
              treeCount: { type: 'number', description: '认种量（棵）' },
              miningStartDate: { type: 'string', description: '挖矿开始时间' },
              batch: { type: 'number', description: '批次号' },
              preMineDays: { type: 'number', description: '授权提前挖的天数' },
              remark: { type: 'string', description: '备注' },
            },
          },
        },
        operatorId: { type: 'string', description: '操作管理员ID' },
        operatorName: { type: 'string', description: '操作管理员名称' },
        reason: { type: 'string', description: '补发原因（必填）' },
      },
    },
  })
  async executeBatchMining(@Body() body: BatchMiningRequest) {
    return this.batchMiningService.execute(body);
  }

  @Get('batch-mining/execution')
  @Public()
  @ApiOperation({ summary: '获取批量补发执行记录（含明细）' })
  async getBatchMiningExecution() {
    const execution = await this.batchMiningService.getExecution();
    if (!execution) {
      throw new HttpException('尚未执行过批量补发', HttpStatus.NOT_FOUND);
    }
    return execution;
  }

  @Get('batch-mining/records/:accountSequence')
  @Public()
  @ApiOperation({ summary: '获取用户的批量补发记录' })
  @ApiParam({ name: 'accountSequence', type: String, description: '用户账户序列号' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'pageSize', required: false, type: Number })
  async getUserBatchMiningRecords(
    @Param('accountSequence') accountSequence: string,
    @Query('page') page?: string,
    @Query('pageSize') pageSize?: string,
  ) {
    const pageNum = page ? parseInt(page, 10) : 1;
    const pageSizeNum = pageSize ? parseInt(pageSize, 10) : 20;
    const skip = (pageNum - 1) * pageSizeNum;

    const [records, total] = await Promise.all([
      this.prisma.batchMiningRecord.findMany({
        where: { accountSequence },
        orderBy: [{ phase: 'asc' }],
        skip,
        take: pageSizeNum,
      }),
      this.prisma.batchMiningRecord.count({
        where: { accountSequence },
      }),
    ]);

    // 计算该用户的总补发金额
    const totalAmount = await this.prisma.batchMiningRecord.aggregate({
      where: { accountSequence },
      _sum: { amount: true },
    });

    return {
      records: records.map((r) => ({
        id: r.id,
        accountSequence: r.accountSequence,
        batch: r.batch,
        phase: r.phase,
        treeCount: r.treeCount,
        daysInPhase: r.daysInPhase,
        preMineDays: r.preMineDays,
        userContribution: r.userContribution.toString(),
        networkContribution: r.networkContribution.toString(),
        contributionRatio: r.contributionRatio.toString(),
        totalSeconds: r.totalSeconds.toString(),
        amount: r.amount.toString(),
        remark: r.remark,
        createdAt: r.createdAt,
      })),
      total,
      page: pageNum,
      pageSize: pageSizeNum,
      totalAmount: totalAmount._sum.amount?.toString() || '0',
    };
  }
}
