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

export interface MiningStatsDto {
  // 配置信息
  isActive: boolean;
  currentEra: number;
  eraStartDate: Date | null;
  activatedAt: Date | null;

  // 分配信息
  totalShares: string;
  distributionPool: string;
  remainingDistribution: string;
  secondDistribution: string;

  // 参与信息
  totalContribution: string;
  participantCount: number;
  totalMined: string;

  // 价格信息
  currentPrice: string;
  priceChangePercent24h: number | null;
}

export interface MiningRankingDto {
  rank: number;
  accountSequence: string;
  totalMined: string;
  totalContribution: string;
}

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

  async execute(): Promise<MiningStatsDto> {
    const [config, latestPrice, price24hAgo, totalMined, participantCount, totalContribution] =
      await Promise.all([
        this.configRepository.getConfig(),
        this.priceRepository.getLatestSnapshot(),
        this.get24hAgoPrice(),
        this.getTotalMined(),
        this.accountRepository.countAccountsWithContribution(),
        this.accountRepository.getTotalContribution(),
      ]);

    let priceChangePercent24h: number | null = null;
    if (latestPrice && price24hAgo) {
      const currentPrice = latestPrice.price.value.toNumber();
      const oldPrice = price24hAgo.price.value.toNumber();
      if (oldPrice > 0) {
        priceChangePercent24h = ((currentPrice - oldPrice) / oldPrice) * 100;
      }
    }

    return {
      isActive: config?.isActive || false,
      currentEra: config?.currentEra || 1,
      eraStartDate: config?.eraStartDate || null,
      activatedAt: config?.activatedAt || null,
      totalShares: config?.totalShares.toString() || '0',
      distributionPool: config?.distributionPool.toString() || '0',
      remainingDistribution: config?.remainingDistribution.toString() || '0',
      secondDistribution: config?.secondDistribution.toString() || '0',
      totalContribution: totalContribution.toString(),
      participantCount,
      totalMined: totalMined.toString(),
      currentPrice: latestPrice?.price.toString() || '1',
      priceChangePercent24h,
    };
  }

  async getRanking(limit: number = 100): Promise<MiningRankingDto[]> {
    const topMiners = await this.accountRepository.getTopMiners(limit);

    return topMiners.map((account, index) => ({
      rank: index + 1,
      accountSequence: account.accountSequence,
      totalMined: account.totalMined.toString(),
      totalContribution: account.totalContribution.toString(),
    }));
  }

  private async getTotalMined(): Promise<string> {
    const result = await this.prisma.miningAccount.aggregate({
      _sum: { totalMined: true },
    });
    return (result._sum.totalMined || 0).toString();
  }

  private async get24hAgoPrice() {
    const time24hAgo = new Date();
    time24hAgo.setHours(time24hAgo.getHours() - 24);
    return this.priceRepository.getSnapshotAt(time24hAgo);
  }
}
