// Predictive Stress Module Service

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { LiquidityStressEvent } from './types';
import { liquidityMonitorService } from './liquidity-monitor.service';
import { logger } from '@/infrastructure/monitoring/logger';


export class StressPredictorService {
  /**
   * Predict liquidity stress events
   */
  async predictStressEvents(): Promise<LiquidityStressEvent[]> {
    const sovereignBanks = await prisma.sovereign_banks.findMany({
      where: { status: 'active' },
    });

    const events: LiquidityStressEvent[] = [];

    for (const bank of sovereignBanks) {
      const prediction = await this.predictStressForSovereign(bank.id);
      if (prediction) {
        events.push(prediction);

        // Store prediction
        await prisma.liquidity_stress_events.create({
          data: {
            id: prediction.id,
            eventId: prediction.eventId,
            sovereignBankId: prediction.sovereignBankId,
            predictedAt: prediction.predictedAt,
            predictedStressDate: prediction.predictedStressDate,
            stressLevel: prediction.stressLevel,
            predictedLiquidityRatio: prediction.predictedLiquidityRatio,
            confidence: prediction.confidence,
            status: prediction.status,
          },
        });
      }
    }

    logger.info(`Predicted ${events.length} liquidity stress events`);

    return events;
  }

  /**
   * Predict stress for a specific sovereign
   */
  private async predictStressForSovereign(
    sovereignBankId: string
  ): Promise<LiquidityStressEvent | null> {
    // Get current SXLR
    const sxlr = await liquidityMonitorService.getSXLR(sovereignBankId);
    if (!sxlr) {
      return null;
    }

    // Get historical SXLR trends
    const historicalRatios = await prisma.sovereign_liquidity_ratios.findMany({
      where: {
        sovereignBankId,
        calculatedAt: {
          gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
        },
      },
      orderBy: { calculatedAt: 'desc' },
      take: 10,
    });

    // Calculate trend
    const trend = this.calculateTrend(historicalRatios.map((r) => Number(r.ratio)));

    // Predict future ratio
    const predictedRatio = sxlr.ratio + (trend * 7); // 7 days ahead

    // Determine stress level
    let stressLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL' = 'LOW';
    if (predictedRatio < 50) {
      stressLevel = 'CRITICAL';
    } else if (predictedRatio < 70) {
      stressLevel = 'HIGH';
    } else if (predictedRatio < 85) {
      stressLevel = 'MEDIUM';
    }

    // Only create event if stress is predicted
    if (stressLevel === 'LOW') {
      return null;
    }

    // Calculate confidence based on trend consistency
    const confidence = Math.min(1.0, Math.abs(trend) / 10);

    return {
      id: uuidv4(),
      eventId: `STRESS-${sovereignBankId}-${Date.now()}`,
      sovereignBankId,
      predictedAt: new Date(),
      predictedStressDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days ahead
      stressLevel,
      predictedLiquidityRatio: predictedRatio,
      confidence,
      status: 'PREDICTED',
    };
  }

  /**
   * Calculate trend from historical data
   */
  private calculateTrend(values: number[]): number {
    if (values.length < 2) {
      return 0;
    }

    // Simple linear regression
    const n = values.length;
    const sumX = (n * (n - 1)) / 2;
    const sumY = values.reduce((sum, val) => sum + val, 0);
    const sumXY = values.reduce((sum, val, idx) => sum + val * idx, 0);
    const sumX2 = (n * (n - 1) * (2 * n - 1)) / 6;

    const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);

    return slope;
  }

  /**
   * Get predicted stress events
   */
  async getPredictedStressEvents(sovereignBankId?: string) {
    const where: any = {
      status: 'PREDICTED',
    };

    if (sovereignBankId) {
      where.sovereignBankId = sovereignBankId;
    }

    return prisma.liquidity_stress_events.findMany({
      where,
      orderBy: { predictedStressDate: 'asc' },
    });
  }
}

export const stressPredictorService = new StressPredictorService();

