// Real-Time Liquidity Monitor Service

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { SovereignLiquidityRatio } from './types';
import { liquidityScoreService } from '../glp/liquidity-score.service';
import { logger } from '@/infrastructure/monitoring/logger';


export class LiquidityMonitorService {
  /**
   * Monitor real-time liquidity for all sovereigns
   */
  async monitorLiquidity(): Promise<SovereignLiquidityRatio[]> {
    const sovereignBanks = await prisma.sovereign_banks.findMany({
      where: { status: 'active' },
    });

    const ratios: SovereignLiquidityRatio[] = [];

    for (const bank of sovereignBanks) {
      const ratio = await this.calculateSXLR(bank.id);
      ratios.push(ratio);

      // Store ratio
      await prisma.sovereign_liquidity_ratios.upsert({
        where: { sovereignBankId: bank.id },
        create: {
          id: `SXLR-${bank.id}-${Date.now()}`,
          sovereignBankId: bank.id,
          ratio: ratio.ratio,
          riskFactors: ratio.riskFactors,
        },
        update: {
          ratio: ratio.ratio,
          riskFactors: ratio.riskFactors,
        },
      });
    }

    logger.info(`Monitored liquidity for ${ratios.length} sovereigns`);

    return ratios;
  }

  /**
   * Calculate Sovereign Liquidity Ratio (SXLR)
   */
  async calculateSXLR(sovereignBankId: string): Promise<SovereignLiquidityRatio> {
    // Get liquidity score
    const liquidityScore = await liquidityScoreService.getLiquidityScore(sovereignBankId);
    const score = liquidityScore ? Number(liquidityScore.score) : 0;

    // Get available liquidity from GLP
    const glpPool = await prisma.global_liquidity_pools.findFirst({
      where: {},
      orderBy: { createdAt: 'desc' },
    });

    const availableLiquidity = glpPool ? Number(glpPool.availableLiquidity) : 0;

    // Get sovereign's account balances
    const accounts = await prisma.bank_accounts.findMany({
      where: {
        sovereignBankId,
        status: 'active',
      },
    });

    const totalBalance = accounts.reduce(
      (sum, acc) => sum + Number(acc.balance),
      0
    );

    // Calculate ratio
    const ratio = totalBalance > 0
      ? (availableLiquidity / totalBalance) * 100
      : 0;

    // Identify risk factors
    const riskFactors: string[] = [];
    if (score < 85) {
      riskFactors.push('LOW_LIQUIDITY_SCORE');
    }
    if (ratio < 50) {
      riskFactors.push('LOW_SXLR');
    }
    if (availableLiquidity < 1000000) {
      riskFactors.push('LOW_GLP_AVAILABILITY');
    }

    return {
      sovereignBankId,
      ratio,
      calculatedAt: new Date(),
      riskFactors,
    };
  }

  /**
   * Get current SXLR for sovereign
   */
  async getSXLR(sovereignBankId: string): Promise<SovereignLiquidityRatio | null> {
    const sxlr = await prisma.sovereign_liquidity_ratios.findUnique({
      where: { sovereignBankId },
    });

    if (!sxlr) {
      return null;
    }

    return {
      sovereignBankId: sxlr.sovereignBankId,
      ratio: Number(sxlr.ratio),
      calculatedAt: sxlr.calculatedAt,
      riskFactors: sxlr.riskFactors as string[],
    };
  }

  /**
   * Check if liquidity threshold is breached
   */
  async isThresholdBreached(sovereignBankId: string, threshold: number = 85): Promise<boolean> {
    const sxlr = await this.getSXLR(sovereignBankId);
    if (!sxlr) {
      return false;
    }

    return sxlr.ratio < threshold;
  }
}

export const liquidityMonitorService = new LiquidityMonitorService();

