// DSDM Ladder Service
// Maturity laddering and rollovers

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


export interface DebtLadderRequest {
  sovereignBankId: string;
  maturityDate: Date;
  principalAmount: string;
  currencyCode: string;
}

export interface RolloverRequest {
  sovereignBankId: string;
  originalLadderId: string;
  rolloverAmount: string;
  currencyCode: string;
  newMaturityDate: Date;
  fundingSource?: string; // cbdc, fiat
}

export class DsdmLadderService {
  /**
   * Create debt ladder
   */
  async createLadder(request: DebtLadderRequest): Promise<{ ladderId: string }> {
    const ladderId = `LADDER-${uuidv4()}`;

    const ladder = await prisma.debt_ladders.create({
      data: {
        ladderId,
        sovereignBankId: request.sovereignBankId,
        maturityDate: request.maturityDate,
        principalAmount: new Decimal(request.principalAmount),
        currencyCode: request.currencyCode,
        status: 'active',
      },
    });

    return {
      ladderId: ladder.ladderId,
    };
  }

  /**
   * Get maturity ladder for sovereign bank
   */
  async getMaturityLadder(sovereignBankId: string): Promise<any[]> {
    const ladders = await prisma.debt_ladders.findMany({
      where: {
        sovereignBankId,
        status: 'active',
      },
      orderBy: { maturityDate: 'asc' },
    });

    return ladders;
  }

  /**
   * Execute rollover
   */
  async executeRollover(request: RolloverRequest): Promise<{
    rolloverId: string;
    newLadderId?: string;
  }> {
    // Get original ladder
    const originalLadder = await prisma.debt_ladders.findUnique({
      where: { ladderId: request.originalLadderId },
    });

    if (!originalLadder) {
      throw new Error(`Ladder not found: ${request.originalLadderId}`);
    }

    if (originalLadder.sovereignBankId !== request.sovereignBankId) {
      throw new Error('Ladder does not belong to sovereign bank');
    }

    // Create new ladder for rollover
    const newLadder = await this.createLadder({
      sovereignBankId: request.sovereignBankId,
      maturityDate: request.newMaturityDate,
      principalAmount: request.rolloverAmount,
      currencyCode: request.currencyCode,
    });

    // Create rollover record
    const rolloverId = `ROLLOVER-${uuidv4()}`;
    const rollover = await prisma.debt_rollovers.create({
      data: {
        rolloverId,
        sovereignBankId: request.sovereignBankId,
        originalLadderId: request.originalLadderId,
        newLadderId: newLadder.ladderId,
        rolloverAmount: new Decimal(request.rolloverAmount),
        currencyCode: request.currencyCode,
        fundingSource: request.fundingSource || 'cbdc',
        status: 'executed',
        executedAt: new Date(),
      },
    });

    // Update original ladder
    await prisma.debt_ladders.update({
      where: { ladderId: request.originalLadderId },
      data: {
        status: 'rolled_over',
        rolloverContractId: rolloverId,
      },
    });

    return {
      rolloverId: rollover.rolloverId,
      newLadderId: newLadder.ladderId,
    };
  }

  /**
   * Get rollover history
   */
  async getRolloverHistory(sovereignBankId: string): Promise<any[]> {
    const rollovers = await prisma.debt_rollovers.findMany({
      where: { sovereignBankId },
      orderBy: { executedAt: 'desc' },
    });

    return rollovers;
  }

  /**
   * Get upcoming maturities
   */
  async getUpcomingMaturities(
    sovereignBankId: string,
    daysAhead: number = 90
  ): Promise<any[]> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() + daysAhead);

    const ladders = await prisma.debt_ladders.findMany({
      where: {
        sovereignBankId,
        status: 'active',
        maturityDate: {
          lte: cutoffDate,
        },
      },
      orderBy: { maturityDate: 'asc' },
    });

    return ladders;
  }
}

export const dsdmLadderService = new DsdmLadderService();

