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

export interface BlackHoleEntity {
  id: string;
  totalBurned: ShareAmount;
  targetBurn: ShareAmount;
  remainingBurn: ShareAmount;
  lastBurnMinute: Date | null;
}

export interface BurnRecordEntity {
  id: string;
  blackHoleId: string;
  burnMinute: Date;
  burnAmount: ShareAmount;
  remainingTarget: ShareAmount;
}

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

  async getBlackHole(): Promise<BlackHoleEntity | null> {
    const record = await this.prisma.blackHole.findFirst();
    if (!record) {
      return null;
    }
    return this.toDomain(record);
  }

  async initializeBlackHole(targetBurn: ShareAmount): Promise<void> {
    const existing = await this.prisma.blackHole.findFirst();
    if (existing) {
      return;
    }

    await this.prisma.blackHole.create({
      data: {
        totalBurned: 0,
        targetBurn: targetBurn.value,
        remainingBurn: targetBurn.value,
      },
    });
  }

  async recordBurn(burnMinute: Date, burnAmount: ShareAmount): Promise<void> {
    const blackHole = await this.prisma.blackHole.findFirst();
    if (!blackHole) {
      throw new Error('Black hole not initialized');
    }

    const newTotalBurned = new ShareAmount(blackHole.totalBurned).add(burnAmount);
    const newRemainingBurn = new ShareAmount(blackHole.targetBurn).subtract(newTotalBurned);

    await this.prisma.$transaction([
      this.prisma.blackHole.update({
        where: { id: blackHole.id },
        data: {
          totalBurned: newTotalBurned.value,
          remainingBurn: newRemainingBurn.value,
          lastBurnMinute: burnMinute,
        },
      }),
      this.prisma.burnRecord.create({
        data: {
          blackHoleId: blackHole.id,
          burnMinute,
          burnAmount: burnAmount.value,
          remainingTarget: newRemainingBurn.value,
        },
      }),
    ]);
  }

  async getBurnRecords(page: number, pageSize: number): Promise<{
    data: BurnRecordEntity[];
    total: number;
  }> {
    const [records, total] = await Promise.all([
      this.prisma.burnRecord.findMany({
        orderBy: { burnMinute: 'desc' },
        skip: (page - 1) * pageSize,
        take: pageSize,
      }),
      this.prisma.burnRecord.count(),
    ]);

    return {
      data: records.map((r) => ({
        id: r.id,
        blackHoleId: r.blackHoleId,
        burnMinute: r.burnMinute,
        burnAmount: new ShareAmount(r.burnAmount),
        remainingTarget: new ShareAmount(r.remainingTarget),
      })),
      total,
    };
  }

  private toDomain(record: any): BlackHoleEntity {
    return {
      id: record.id,
      totalBurned: new ShareAmount(record.totalBurned),
      targetBurn: new ShareAmount(record.targetBurn),
      remainingBurn: new ShareAmount(record.remainingBurn),
      lastBurnMinute: record.lastBurnMinute,
    };
  }
}
