import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { ShareAmount } from '../../../domain/value-objects/share-amount.vo';
import { Price } from '../../../domain/value-objects/price.vo';

export interface PriceSnapshotEntity {
  id: string;
  snapshotTime: Date;
  price: Price;
  sharePool: ShareAmount;
  blackHoleAmount: ShareAmount;
  circulationPool: ShareAmount;
  effectiveDenominator: ShareAmount;
}

@Injectable()
export class PriceSnapshotRepository {
  constructor(private readonly prisma: PrismaService) {}

  async getLatestSnapshot(): Promise<PriceSnapshotEntity | null> {
    const record = await this.prisma.priceSnapshot.findFirst({
      orderBy: { snapshotTime: 'desc' },
    });

    if (!record) {
      return null;
    }

    return this.toDomain(record);
  }

  async getSnapshotAt(time: Date): Promise<PriceSnapshotEntity | null> {
    const record = await this.prisma.priceSnapshot.findFirst({
      where: { snapshotTime: { lte: time } },
      orderBy: { snapshotTime: 'desc' },
    });

    if (!record) {
      return null;
    }

    return this.toDomain(record);
  }

  async saveSnapshot(snapshot: Omit<PriceSnapshotEntity, 'id'>): Promise<void> {
    await this.prisma.priceSnapshot.upsert({
      where: { snapshotTime: snapshot.snapshotTime },
      create: {
        snapshotTime: snapshot.snapshotTime,
        price: snapshot.price.value,
        sharePool: snapshot.sharePool.value,
        blackHoleAmount: snapshot.blackHoleAmount.value,
        circulationPool: snapshot.circulationPool.value,
        effectiveDenominator: snapshot.effectiveDenominator.value,
      },
      update: {
        price: snapshot.price.value,
        sharePool: snapshot.sharePool.value,
        blackHoleAmount: snapshot.blackHoleAmount.value,
        circulationPool: snapshot.circulationPool.value,
        effectiveDenominator: snapshot.effectiveDenominator.value,
      },
    });
  }

  async getPriceHistory(
    startTime: Date,
    endTime: Date,
    interval: 'minute' | 'hour' | 'day',
  ): Promise<PriceSnapshotEntity[]> {
    const records = await this.prisma.priceSnapshot.findMany({
      where: {
        snapshotTime: {
          gte: startTime,
          lte: endTime,
        },
      },
      orderBy: { snapshotTime: 'asc' },
    });

    // 根据间隔过滤数据
    if (interval === 'minute') {
      return records.map((r) => this.toDomain(r));
    }

    // 对于小时和天级别，需要聚合
    const grouped = new Map<string, any>();
    for (const record of records) {
      let key: string;
      if (interval === 'hour') {
        key = record.snapshotTime.toISOString().substring(0, 13);
      } else {
        key = record.snapshotTime.toISOString().substring(0, 10);
      }

      if (!grouped.has(key) || record.snapshotTime > grouped.get(key).snapshotTime) {
        grouped.set(key, record);
      }
    }

    return Array.from(grouped.values()).map((r) => this.toDomain(r));
  }

  private toDomain(record: any): PriceSnapshotEntity {
    return {
      id: record.id,
      snapshotTime: record.snapshotTime,
      price: new Price(record.price),
      sharePool: new ShareAmount(record.sharePool),
      blackHoleAmount: new ShareAmount(record.blackHoleAmount),
      circulationPool: new ShareAmount(record.circulationPool),
      effectiveDenominator: new ShareAmount(record.effectiveDenominator),
    };
  }
}
