import { Injectable } from '@nestjs/common';
import { MiningAccountRepository } from '../../infrastructure/persistence/repositories/mining-account.repository';
import { MiningConfigRepository } from '../../infrastructure/persistence/repositories/mining-config.repository';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';

export interface MiningAccountDto {
  accountSequence: string;
  totalMined: string;
  availableBalance: string;
  frozenBalance: string;
  totalBalance: string;
  totalContribution: string;
  perSecondEarning: string;  // 每秒收益 = (用户贡献 / 全网贡献) × 每秒分配量
  lastSyncedAt: Date | null;
  firstMiningDate: Date | null;  // 首次挖矿时间（用于730天倒计时）
}

export interface MiningRecordDto {
  id: string;
  miningMinute: Date;
  contributionRatio: string;
  totalContribution: string;
  secondDistribution: string;
  minedAmount: string;
  createdAt: Date;
}

export interface MiningTransactionDto {
  id: string;
  type: string;
  amount: string;
  balanceBefore: string;
  balanceAfter: string;
  referenceId: string | null;
  referenceType: string | null;
  description: string | null;
  createdAt: Date;
}

@Injectable()
export class GetMiningAccountQuery {
  constructor(
    private readonly accountRepository: MiningAccountRepository,
    private readonly configRepository: MiningConfigRepository,
    private readonly prisma: PrismaService,
  ) {}

  async execute(accountSequence: string): Promise<MiningAccountDto | null> {
    const account = await this.accountRepository.findByAccountSequence(accountSequence);
    if (!account) {
      return null;
    }

    // 计算每秒收益 = (用户贡献 / 全网贡献) × 每秒分配量
    // 只有在挖矿系统激活时才返回非零值
    let perSecondEarning = '0';
    let firstMiningDate: Date | null = null;
    try {
      const [config, totalContribution, firstRecord] = await Promise.all([
        this.configRepository.getConfig(),
        this.accountRepository.getTotalContribution(),
        this.prisma.miningRecord.findFirst({
          where: { accountSequence },
          orderBy: { miningMinute: 'asc' },
          select: { miningMinute: true },
        }),
      ]);

      firstMiningDate = firstRecord?.miningMinute ?? null;

      // 检查挖矿系统是否激活
      if (config && config.isActive && totalContribution.value.toNumber() > 0) {
        const userContribution = account.totalContribution.value.toNumber();
        const secondDistribution = config.secondDistribution.value.toNumber();
        const ratio = userContribution / totalContribution.value.toNumber();
        perSecondEarning = (ratio * secondDistribution).toFixed(8);
      }
    } catch {
      // 如果计算失败，返回 0
    }

    return {
      accountSequence: account.accountSequence,
      totalMined: account.totalMined.toString(),
      availableBalance: account.availableBalance.toString(),
      frozenBalance: account.frozenBalance.toString(),
      totalBalance: account.totalBalance.toString(),
      totalContribution: account.totalContribution.toString(),
      perSecondEarning,
      lastSyncedAt: account.lastSyncedAt,
      firstMiningDate,
    };
  }

  async getMiningRecords(
    accountSequence: string,
    page: number = 1,
    pageSize: number = 50,
  ): Promise<{ data: MiningRecordDto[]; total: number }> {
    const [records, total] = await Promise.all([
      this.prisma.miningRecord.findMany({
        where: { accountSequence },
        orderBy: { miningMinute: 'desc' },
        skip: (page - 1) * pageSize,
        take: pageSize,
      }),
      this.prisma.miningRecord.count({ where: { accountSequence } }),
    ]);

    return {
      data: records.map((r) => ({
        id: r.id,
        miningMinute: r.miningMinute,
        contributionRatio: r.contributionRatio.toString(),
        totalContribution: r.totalContribution.toString(),
        secondDistribution: r.secondDistribution.toString(),
        minedAmount: r.minedAmount.toString(),
        createdAt: r.createdAt,
      })),
      total,
    };
  }

  async getTransactions(
    accountSequence: string,
    page: number = 1,
    pageSize: number = 50,
  ): Promise<{ data: MiningTransactionDto[]; total: number }> {
    const [records, total] = await Promise.all([
      this.prisma.miningTransaction.findMany({
        where: { accountSequence },
        orderBy: { createdAt: 'desc' },
        skip: (page - 1) * pageSize,
        take: pageSize,
      }),
      this.prisma.miningTransaction.count({ where: { accountSequence } }),
    ]);

    return {
      data: records.map((r) => ({
        id: r.id,
        type: r.type,
        amount: r.amount.toString(),
        balanceBefore: r.balanceBefore.toString(),
        balanceAfter: r.balanceAfter.toString(),
        referenceId: r.referenceId,
        referenceType: r.referenceType,
        description: r.description,
        createdAt: r.createdAt,
      })),
      total,
    };
  }
}
