import { Injectable } from '@nestjs/common';
import { PriceSnapshotRepository, PriceSnapshotEntity } from '../../infrastructure/persistence/repositories/price-snapshot.repository';

export interface PriceDto {
  snapshotTime: Date;
  price: string;
  sharePool: string;
  blackHoleAmount: string;
  circulationPool: string;
  effectiveDenominator: string;
}

export interface KLineDataDto {
  time: Date;
  open: string;
  high: string;
  low: string;
  close: string;
}

@Injectable()
export class GetPriceQuery {
  constructor(private readonly priceRepository: PriceSnapshotRepository) {}

  async getCurrentPrice(): Promise<PriceDto | null> {
    const snapshot = await this.priceRepository.getLatestSnapshot();
    if (!snapshot) {
      return null;
    }
    return this.toDto(snapshot);
  }

  async getPriceAt(time: Date): Promise<PriceDto | null> {
    const snapshot = await this.priceRepository.getSnapshotAt(time);
    if (!snapshot) {
      return null;
    }
    return this.toDto(snapshot);
  }

  async getPriceHistory(
    startTime: Date,
    endTime: Date,
    interval: 'minute' | 'hour' | 'day',
  ): Promise<PriceDto[]> {
    const snapshots = await this.priceRepository.getPriceHistory(startTime, endTime, interval);
    return snapshots.map((s) => this.toDto(s));
  }

  async getKLineData(
    startTime: Date,
    endTime: Date,
    interval: 'minute' | 'hour' | 'day',
  ): Promise<KLineDataDto[]> {
    const snapshots = await this.priceRepository.getPriceHistory(startTime, endTime, 'minute');

    // 按间隔分组
    const grouped = new Map<string, PriceSnapshotEntity[]>();

    for (const snapshot of snapshots) {
      let key: string;
      if (interval === 'minute') {
        key = snapshot.snapshotTime.toISOString().substring(0, 16);
      } else if (interval === 'hour') {
        key = snapshot.snapshotTime.toISOString().substring(0, 13);
      } else {
        key = snapshot.snapshotTime.toISOString().substring(0, 10);
      }

      if (!grouped.has(key)) {
        grouped.set(key, []);
      }
      grouped.get(key)!.push(snapshot);
    }

    // 生成 K 线数据
    const kLineData: KLineDataDto[] = [];

    for (const [key, items] of grouped) {
      if (items.length === 0) continue;

      const prices = items.map((i) => i.price.value.toNumber());
      const times = items.map((i) => i.snapshotTime);

      kLineData.push({
        time: times[0],
        open: items[0].price.toString(),
        high: Math.max(...prices).toString(),
        low: Math.min(...prices).toString(),
        close: items[items.length - 1].price.toString(),
      });
    }

    return kLineData.sort((a, b) => a.time.getTime() - b.time.getTime());
  }

  private toDto(snapshot: PriceSnapshotEntity): PriceDto {
    return {
      snapshotTime: snapshot.snapshotTime,
      price: snapshot.price.toString(),
      sharePool: snapshot.sharePool.toString(),
      blackHoleAmount: snapshot.blackHoleAmount.toString(),
      circulationPool: snapshot.circulationPool.toString(),
      effectiveDenominator: snapshot.effectiveDenominator.toString(),
    };
  }
}
