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

/**
 * 挖矿计算领域服务
 *
 * 注意：销毁机制由 trading-service 负责，mining-service 不再执行销毁计算
 */
export class MiningCalculatorService {
  // 总积分股数量: 100.02亿 (SHARE_POOL_A: 100亿 + SHARE_POOL_B: 200万)
  static readonly TOTAL_SHARES = new ShareAmount('10002000000');

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

  // 减半周期: 2年（秒）
  static readonly HALVING_PERIOD_SECONDS = 2 * 365 * 24 * 60 * 60; // 63,072,000秒

  /**
   * 计算纪元初始分配量
   * 每个纪元分配量减半
   */
  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 secondDistribution 每秒分配量
   */
  calculateUserMiningReward(
    userContribution: ShareAmount,
    totalContribution: ShareAmount,
    secondDistribution: ShareAmount,
  ): ShareAmount {
    if (totalContribution.isZero() || userContribution.isZero()) {
      return ShareAmount.zero();
    }

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

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

  /**
   * 计算剩余挖矿秒数
   */
  calculateRemainingSeconds(eraStartDate: Date, halvingPeriodSeconds: number): number {
    const now = new Date();
    const elapsedMs = now.getTime() - eraStartDate.getTime();
    const elapsedSeconds = Math.floor(elapsedMs / 1000);
    return Math.max(0, halvingPeriodSeconds - elapsedSeconds);
  }
}
