// Stablecoin Reserves Service
// Daily reserve snapshots

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';


export interface ReserveSnapshotRequest {
  stablecoinId: string;
  snapshotDate: Date;
}

export interface ReserveSnapshotResult {
  reserveId: string;
  totalReserves: string;
  totalSupply: string;
  collateralizationRatio: string;
  status: string;
}

export class StablecoinReservesService {
  /**
   * Create daily reserve snapshot
   */
  async createSnapshot(
    request: ReserveSnapshotRequest
  ): Promise<ReserveSnapshotResult> {
    const stablecoin = await prisma.sovereignStablecoin.findUnique({
      where: { stablecoinId: request.stablecoinId },
      include: {
        collaterals: {
          where: { status: 'active' },
        },
      },
    });

    if (!stablecoin) {
      throw new Error(`Stablecoin not found: ${request.stablecoinId}`);
    }

    // Calculate total reserves
    const totalReserves = stablecoin.collaterals.reduce(
      (sum, coll) => sum.plus(coll.valuation),
      new Decimal(0)
    );

    // Get reserve breakdown by asset type
    const reserveBreakdown: Record<string, string> = {};
    for (const coll of stablecoin.collaterals) {
      if (!reserveBreakdown[coll.assetType]) {
        reserveBreakdown[coll.assetType] = '0';
      }
      reserveBreakdown[coll.assetType] = new Decimal(reserveBreakdown[coll.assetType])
        .plus(coll.valuation)
        .toString();
    }

    // Calculate collateralization ratio
    const collateralizationRatio = stablecoin.totalSupply.isZero()
      ? new Decimal(1.0)
      : totalReserves.div(stablecoin.totalSupply);

    // Create reserve snapshot
    const reserveId = `RESERVE-${uuidv4()}`;
    const reserve = await prisma.stablecoinReserve.create({
      data: {
        reserveId,
        stablecoinId: request.stablecoinId,
        snapshotDate: request.snapshotDate,
        totalReserves,
        totalSupply: stablecoin.totalSupply,
        collateralizationRatio,
        reserveBreakdown,
        status: 'pending',
      },
    });

    return {
      reserveId: reserve.reserveId,
      totalReserves: reserve.totalReserves.toString(),
      totalSupply: reserve.totalSupply.toString(),
      collateralizationRatio: reserve.collateralizationRatio.toString(),
      status: reserve.status,
    };
  }

  /**
   * Verify and publish snapshot
   */
  async verifySnapshot(reserveId: string): Promise<void> {
    const reserve = await prisma.stablecoinReserve.findUnique({
      where: { reserveId },
    });

    if (!reserve) {
      throw new Error(`Reserve snapshot not found: ${reserveId}`);
    }

    // Verify collateralization ratio >= 1.0
    if (reserve.collateralizationRatio.lessThan(new Decimal(1.0))) {
      throw new Error('Reserve snapshot verification failed: insufficient collateralization');
    }

    await prisma.stablecoinReserve.update({
      where: { reserveId },
      data: {
        status: 'verified',
        verifiedAt: new Date(),
      },
    });
  }

  /**
   * Publish snapshot
   */
  async publishSnapshot(reserveId: string): Promise<void> {
    const reserve = await prisma.stablecoinReserve.findUnique({
      where: { reserveId },
    });

    if (!reserve) {
      throw new Error(`Reserve snapshot not found: ${reserveId}`);
    }

    if (reserve.status !== 'verified') {
      throw new Error(`Reserve snapshot must be verified before publishing: ${reserve.status}`);
    }

    await prisma.stablecoinReserve.update({
      where: { reserveId },
      data: {
        status: 'published',
      },
    });
  }

  /**
   * Get latest snapshot
   */
  async getLatestSnapshot(stablecoinId: string): Promise<any | null> {
    const reserve = await prisma.stablecoinReserve.findFirst({
      where: { stablecoinId },
      orderBy: { snapshotDate: 'desc' },
    });

    return reserve;
  }

  /**
   * Get snapshot history
   */
  async getSnapshotHistory(
    stablecoinId: string,
    limit: number = 30
  ): Promise<any[]> {
    const reserves = await prisma.stablecoinReserve.findMany({
      where: { stablecoinId },
      orderBy: { snapshotDate: 'desc' },
      take: limit,
    });

    return reserves;
  }
}

export const stablecoinReservesService = new StablecoinReservesService();

