// Treasury & Liquidity Module

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { LiquidityForecast, InterbankCreditLine } from '@/shared/types';
import { accountService } from '@/core/accounts/account.service';
import { sriEnforcementService } from '@/core/risk/sri/sri-enforcement.service';
import { v4 as uuidv4 } from 'uuid';


export class TreasuryService {
  /**
   * Calculate Liquidity Coverage Ratio (LCR)
   */
  async calculateLCR(sovereignBankId: string): Promise<string> {
    const accounts = await accountService.getAccountsBySovereign(sovereignBankId);
    
    // Calculate High-Quality Liquid Assets (HQLA)
    const hqla = accounts
      .filter((acc) => acc.assetType === 'fiat' || acc.assetType === 'cbdc')
      .reduce((sum, acc) => sum + parseFloat(acc.availableBalance), 0);

    // Calculate net cash outflows (simplified)
    const netOutflows = hqla * 0.1; // Mock calculation

    const lcr = netOutflows > 0 ? hqla / netOutflows : 0;
    return lcr.toFixed(8);
  }

  /**
   * Calculate Net Stable Funding Ratio (NSFR)
   */
  async calculateNSFR(sovereignBankId: string): Promise<string> {
    const accounts = await accountService.getAccountsBySovereign(sovereignBankId);
    
    // Calculate Available Stable Funding (ASF)
    const asf = accounts
      .filter((acc) => acc.accountType === 'treasury')
      .reduce((sum, acc) => sum + parseFloat(acc.balance), 0);

    // Calculate Required Stable Funding (RSF)
    const rsf = asf * 0.85; // Mock calculation

    const nsfr = rsf > 0 ? asf / rsf : 0;
    return nsfr.toFixed(8);
  }

  /**
   * Create liquidity forecast
   */
  async createLiquidityForecast(
    sovereignBankId: string,
    forecastType: 'daily' | 'weekly' | 'monthly'
  ): Promise<LiquidityForecast> {
    const lcr = await this.calculateLCR(sovereignBankId);
    const nsfr = await this.calculateNSFR(sovereignBankId);
    const hqla = await this.calculateHQLA(sovereignBankId);

    const forecast = await prisma.liquidityForecast.create({
      data: {
        sovereignBankId,
        forecastDate: new Date(),
        forecastType,
        lcr: new Decimal(lcr),
        nsfr: new Decimal(nsfr),
        hqla: new Decimal(hqla),
        forecastData: {
          lcr,
          nsfr,
          hqla,
        },
      },
    });

    return {
      id: forecast.id,
      sovereignBankId: forecast.sovereignBankId,
      forecastDate: forecast.forecastDate,
      forecastType: forecast.forecastType as 'daily' | 'weekly' | 'monthly',
      lcr: forecast.lcr?.toString(),
      nsfr: forecast.nsfr?.toString(),
      hqla: forecast.hqla?.toString(),
      forecastData: forecast.forecastData as Record<string, unknown>,
    };
  }

  /**
   * Calculate High-Quality Liquid Assets (HQLA)
   */
  private async calculateHQLA(sovereignBankId: string): Promise<string> {
    const accounts = await accountService.getAccountsBySovereign(sovereignBankId);
    const hqla = accounts
      .filter((acc) => acc.assetType === 'fiat' || acc.assetType === 'cbdc')
      .reduce((sum, acc) => sum + parseFloat(acc.availableBalance), 0);
    return hqla.toFixed(8);
  }

  /**
   * Create interbank credit line
   */
  async createCreditLine(
    sovereignBankId: string,
    counterpartyBankId: string,
    creditLimit: string,
    currencyCode: string,
    expiryDate?: Date
  ): Promise<InterbankCreditLine> {
    const creditLine = await prisma.interbank_credit_lines.create({
      data: {
        sovereignBankId,
        counterpartyBankId,
        creditLimit: new Decimal(creditLimit),
        usedAmount: new Decimal(0),
        availableAmount: new Decimal(creditLimit),
        currencyCode,
        status: 'active',
        expiryDate,
      },
    });

    return {
      id: creditLine.id,
      sovereignBankId: creditLine.sovereignBankId,
      counterpartyBankId: creditLine.counterpartyBankId,
      creditLimit: creditLine.creditLimit.toString(),
      usedAmount: creditLine.usedAmount.toString(),
      availableAmount: creditLine.availableAmount.toString(),
      currencyCode: creditLine.currencyCode,
      status: creditLine.status,
      expiryDate: creditLine.expiryDate || undefined,
    };
  }

  /**
   * Check if liquidity requirements are enforced due to SRI
   */
  async checkSRILiquidityEnforcement(sovereignBankId: string): Promise<boolean> {
    const enforcements = await sriEnforcementService.getActiveEnforcements(sovereignBankId);
    return enforcements.some(
      (e) => e.enforcementType === 'liquidity_requirement' && e.status === 'active'
    );
  }
}

export const treasuryService = new TreasuryService();

