import Decimal from 'decimal.js';
import { ShareAmount } from '../value-objects/share-amount.vo';
import { Price } from '../value-objects/price.vo';

/**
 * 挖矿计算领域服务
 */
export class MiningCalculatorService {
  // 总积分股数量: 100.02B
  static readonly TOTAL_SHARES = new ShareAmount('100020000000');

  // 初始分配池: 200M
  static readonly INITIAL_DISTRIBUTION_POOL = new ShareAmount('200000000');

  // 目标销毁量: 10B
  static readonly BURN_TARGET = new ShareAmount('10000000000');

  // 减半周期: 2年 (分钟)
  static readonly HALVING_PERIOD_MINUTES = 2 * 365 * 24 * 60;

  /**
   * 计算每分钟分配量
   * @param remainingDistribution 剩余可分配量
   * @param eraNumber 当前纪元编号
   * @param remainingMinutesInEra 当前纪元剩余分钟数
   */
  calculateMinuteDistribution(
    remainingDistribution: ShareAmount,
    eraNumber: number,
    remainingMinutesInEra: number,
  ): ShareAmount {
    if (remainingDistribution.isZero() || remainingMinutesInEra <= 0) {
      return ShareAmount.zero();
    }

    // 每分钟分配 = 剩余量 / 剩余分钟数
    return remainingDistribution.divide(remainingMinutesInEra);
  }

  /**
   * 计算纪元初始分配量
   * 每个纪元分配量减半
   */
  calculateEraDistribution(eraNumber: number): ShareAmount {
    // 第1纪元: 100M, 第2纪元: 50M, 第3纪元: 25M...
    const divisor = new Decimal(2).pow(eraNumber - 1);
    const initialEraAmount = MiningCalculatorService.INITIAL_DISTRIBUTION_POOL.divide(2);
    return initialEraAmount.divide(divisor);
  }

  /**
   * 计算用户挖矿收益
   * @param userContribution 用户算力
   * @param totalContribution 总算力
   * @param minuteDistribution 每分钟分配量
   */
  calculateUserMiningReward(
    userContribution: ShareAmount,
    totalContribution: ShareAmount,
    minuteDistribution: ShareAmount,
  ): ShareAmount {
    if (totalContribution.isZero() || userContribution.isZero()) {
      return ShareAmount.zero();
    }

    // 用户收益 = 每分钟分配量 * (用户算力 / 总算力)
    const ratio = userContribution.value.dividedBy(totalContribution.value);
    return minuteDistribution.multiply(ratio);
  }

  /**
   * 计算每分钟销毁量
   * 设计目标: 假设只有黑洞和股池,价格每秒增长1分钱
   * minuteBurn = (burnTarget - currentBurned) / remainingMinutes
   */
  calculateMinuteBurn(
    burnTarget: ShareAmount,
    currentBurned: ShareAmount,
    remainingMinutes: number,
  ): ShareAmount {
    if (remainingMinutes <= 0) {
      return ShareAmount.zero();
    }

    const remaining = burnTarget.subtract(currentBurned);
    if (remaining.isZero()) {
      return ShareAmount.zero();
    }

    return remaining.divide(remainingMinutes);
  }

  /**
   * 计算价格
   * price = sharePool / (totalShares - blackHole - circulationPool)
   */
  calculatePrice(
    sharePool: ShareAmount,
    blackHole: ShareAmount,
    circulationPool: ShareAmount,
  ): Price {
    return Price.calculate(
      sharePool,
      MiningCalculatorService.TOTAL_SHARES,
      blackHole,
      circulationPool,
    );
  }

  /**
   * 计算理论价格（假设只有黑洞,用于验证销毁机制）
   */
  calculateTheoreticalPrice(
    sharePool: ShareAmount,
    blackHole: ShareAmount,
  ): Price {
    return Price.calculate(
      sharePool,
      MiningCalculatorService.TOTAL_SHARES,
      blackHole,
      ShareAmount.zero(),
    );
  }

  /**
   * 计算剩余挖矿分钟数
   */
  calculateRemainingMinutes(eraStartDate: Date, halvingPeriodMinutes: number): number {
    const now = new Date();
    const elapsedMs = now.getTime() - eraStartDate.getTime();
    const elapsedMinutes = Math.floor(elapsedMs / 60000);
    return Math.max(0, halvingPeriodMinutes - elapsedMinutes);
  }

  /**
   * 计算剩余销毁分钟数
   * 假设销毁周期为整个挖矿周期
   */
  calculateRemainingBurnMinutes(startDate: Date, totalMinutes: number): number {
    const now = new Date();
    const elapsedMs = now.getTime() - startDate.getTime();
    const elapsedMinutes = Math.floor(elapsedMs / 60000);
    return Math.max(0, totalMinutes - elapsedMinutes);
  }
}
