// SIRE Optimization Service
// Route cost minimization
// Risk-adjusted routing
// Real-time route updates
// Performance monitoring

import { Decimal } from '@prisma/client/runtime/library';
import { sireRoutingService } from './sire-routing.service';
import { sireMetricsService } from './sire-metrics.service';
import prisma from '@/shared/database/prisma';
import { logger } from '@/infrastructure/monitoring/logger';

export class SireOptimizationService {
  /**
   * Optimize route
   */
  async optimizeRoute(
    sourceBankId: string,
    destinationBankId: string,
    amount: string,
    currencyCode: string
  ): Promise<string> {
    // Recalculate optimal route
    const optimalRouteId = await sireRoutingService.calculateOptimalRoute({
      sourceBankId,
      destinationBankId,
      amount,
      currencyCode,
    });

    // Update route metrics
    await this.updateRouteMetrics(optimalRouteId);

    return optimalRouteId;
  }

  /**
   * Update route metrics
   */
  private async updateRouteMetrics(routeId: string): Promise<void> {
    const route = await prisma.settlement_routes.findUnique({
      where: { routeId },
    });

    if (!route) {
      return;
    }

    // Get latest metrics
    const latestDecision = await prisma.sire_routing_decisions.findFirst({
      where: { routeId },
      orderBy: { decisionTimestamp: 'desc' },
      include: {
        metrics: true,
      },
    });

    if (!latestDecision || !latestDecision.behavioral_metrics) {
      return;
    }

    const metrics = latestDecision.behavioral_metrics;

    // Update route with SIRE metrics
    await prisma.settlement_routes.update({
      where: { routeId },
      data: {
        sireCost: latestDecision.totalCost,
        sriRiskScore: metrics.sriScore || null,
        liquidityPenalty: latestDecision.liquidityPenalty || null,
        ssuAdjustment: latestDecision.ssuAdjustment || null,
        lastUsedAt: new Date(),
      },
    });
  }

  /**
   * Monitor route performance
   */
  async monitorRoutePerformance(routeId: string): Promise<void> {
    // Get recent decisions for route
    const recentDecisions = await prisma.sire_routing_decisions.findMany({
      where: {
        routeId,
      },
      orderBy: { decisionTimestamp: 'desc' },
      take: 100,
    });

    if (recentDecisions.length === 0) {
      return;
    }

    // Calculate average cost
    const totalCost = recentDecisions.reduce(
      (sum, decision) => sum.plus(decision.totalCost),
      new Decimal(0)
    );

    const avgCost = totalCost.div(recentDecisions.length);

    // Update route with performance metrics
    await prisma.settlement_routes.update({
      where: { routeId },
      data: {
        fxCost: avgCost, // Update average FX cost
      },
    });
  }

  /**
   * Update routes in real-time
   */
  async updateRoutesRealTime(): Promise<void> {
    // Get all active routes
    const routes = await prisma.settlement_routes.findMany({
      where: {
        status: 'active',
      },
    });

    // Update each route
    for (const route of routes) {
      try {
        await this.updateRouteMetrics(route.routeId);
        await this.monitorRoutePerformance(route.routeId);
      } catch (error) {
        // Continue with other routes
        logger.error('Error updating route', {
          routeId: route.routeId,
          error: error instanceof Error ? error.message : 'Unknown error',
        });
      }
    }
  }

  /**
   * Risk-adjusted routing
   */
  async calculateRiskAdjustedRoute(
    sourceBankId: string,
    destinationBankId: string,
    amount: string,
    currencyCode: string,
    riskTolerance: string = 'medium'
  ): Promise<string> {
    // Get optimal route
    const optimalRouteId = await sireRoutingService.calculateOptimalRoute({
      sourceBankId,
      destinationBankId,
      amount,
      currencyCode,
    });

    // Get route decision
    const decision = await prisma.sire_routing_decisions.findFirst({
      where: {
        routeId: optimalRouteId,
      },
      orderBy: { decisionTimestamp: 'desc' },
      include: {
        metrics: true,
      },
    });

    if (!decision) {
      return optimalRouteId;
    }

    // Adjust based on risk tolerance
    const riskMultiplier = this.getRiskMultiplier(riskTolerance);
    const adjustedRiskCost = (decision.sriRiskScore || new Decimal(0))
      .mul(riskMultiplier);

    // If adjusted risk is too high, find alternative route
    if (adjustedRiskCost.gt(50)) {
      // Find alternative with lower risk
      const routes = await prisma.settlement_routes.findMany({
        where: {
          OR: [
            {
              sourceBankId,
              destinationBankId,
              currencyCode,
              status: 'active',
            },
            {
              sourceBankId,
              destinationBankId: 'DBIS',
              currencyCode,
              status: 'active',
            },
          ],
        },
      });

      // Find route with lower risk
      for (const route of routes) {
        if (route.routeId === optimalRouteId) {
          continue;
        }

        const routeMetrics = await sireMetricsService.calculateMetrics(
          route.routeId,
          sourceBankId,
          destinationBankId
        );

        const routeRiskCost = (routeMetrics.sriScore || new Decimal(0))
          .mul(riskMultiplier);

        if (routeRiskCost.lt(adjustedRiskCost)) {
          return route.routeId; // Use lower risk route
        }
      }
    }

    return optimalRouteId;
  }

  /**
   * Get risk multiplier based on tolerance
   */
  private getRiskMultiplier(riskTolerance: string): Decimal {
    const multipliers: Record<string, Decimal> = {
      low: new Decimal(1.5), // Lower risk tolerance = higher penalty
      medium: new Decimal(1.0),
      high: new Decimal(0.5), // Higher risk tolerance = lower penalty
    };

    return multipliers[riskTolerance] || new Decimal(1.0);
  }
}

export const sireOptimizationService = new SireOptimizationService();

