// Supranational Reserve Pool Stress Service
// Stress testing for SR-1, SR-2, SR-3 reserve pools

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';
import { logger } from '@/infrastructure/monitoring/logger';
import { gruStressAlgorithmsService } from './gru-stress-algorithms.service';
import { gruSimulationTablesService } from './gru-simulation-tables.service';


export interface ReservePoolStressRequest {
  poolId: 'SR-1' | 'SR-2' | 'SR-3';
  commodityShock?: string; // S1, S2, S3, S4
  fxShock?: string; // F1, F2, F3, F4
  region?: string;
  parameters?: Record<string, unknown>;
}

export interface ReservePoolStressResult {
  stressTestId: string;
  poolId: string;
  commodityShock?: string;
  fxShock?: string;
  gruReserveImpact: Decimal;
  status: string;
}

export class GruReservePoolStressService {
  /**
   * Get or create supranational reserve pool
   */
  async getOrCreateReservePool(
    poolId: 'SR-1' | 'SR-2' | 'SR-3',
    region?: string
  ): Promise<string> {
    let pool = await prisma.supranationalReservePool.findUnique({
      where: { poolId },
    });

    if (!pool) {
      pool = await prisma.supranationalReservePool.create({
        data: {
          poolId,
          poolName: `Supranational Reserve Pool ${poolId}`,
          poolType: 'supranational_reserve',
          region: region || null,
          totalReserves: new Decimal(0),
          availableReserves: new Decimal(0),
          reservedReserves: new Decimal(0),
        },
      });
    }

    return pool.id;
  }

  /**
   * Run stress test on specific reserve pool
   */
  async runReservePoolStress(
    request: ReservePoolStressRequest
  ): Promise<ReservePoolStressResult> {
    logger.info('GRU Reserve Pool Stress: Running reserve pool stress test', {
      request,
    });

    // Get or create pool
    const poolId = await this.getOrCreateReservePool(
      request.poolId,
      request.region
    );

    const pool = await prisma.supranationalReservePool.findUnique({
      where: { id: poolId },
    });

    if (!pool) {
      throw new Error(`Reserve pool not found: ${request.poolId}`);
    }

    // Determine region if not provided
    const region = request.region || pool.region || 'EU';

    // Determine shocks if not provided (use defaults from table)
    const commodityShock = request.commodityShock || this.getDefaultCommodityShock(region);
    const fxShock = request.fxShock || this.getDefaultFxShock(region);

    // Calculate regional impact
    const gruReserveImpact = gruStressAlgorithmsService.calculateRegionalReserveImpact(
      region,
      commodityShock,
      fxShock
    );

    // Create stress test record
    const stressTestId = `RESERVE-STRESS-${uuidv4()}`;
    const stressTest = await prisma.supranationalReservePoolStressTest.create({
      data: {
        stressTestId,
        poolId: pool.id,
        commodityShock,
        fxShock,
        gruReserveImpact,
        testParameters: request.parameters || {},
        status: 'completed',
        testedAt: new Date(),
      },
    });

    logger.info('GRU Reserve Pool Stress: Reserve pool stress test completed', {
      stressTestId,
      poolId: request.poolId,
      gruReserveImpact: gruReserveImpact.toString(),
    });

    return {
      stressTestId,
      poolId: request.poolId,
      commodityShock,
      fxShock,
      gruReserveImpact,
      status: 'completed',
    };
  }

  /**
   * Calculate regional impact
   */
  async calculateRegionalImpact(
    region: string,
    commodityShock: string,
    fxShock: string
  ): Promise<Decimal> {
    return gruStressAlgorithmsService.calculateRegionalReserveImpact(
      region,
      commodityShock,
      fxShock
    );
  }

  /**
   * Get regional reserve pool stress table
   */
  async getRegionalReservePoolTable(): Promise<any> {
    logger.info('GRU Reserve Pool Stress: Generating regional reserve pool table');

    const table = await gruSimulationTablesService.generateRegionalReservePoolTable();

    return {
      tableType: 'regional_reserve_pool',
      tableName: 'Regional Reserve Pool Stress Table',
      data: table,
    };
  }

  /**
   * Get stress test results for a pool
   */
  async getReservePoolStressTests(poolId: string) {
    return await prisma.supranationalReservePoolStressTest.findMany({
      where: { poolId },
      orderBy: { testedAt: 'desc' },
    });
  }

  /**
   * Get reserve pool by ID
   */
  async getReservePool(poolId: 'SR-1' | 'SR-2' | 'SR-3') {
    return await prisma.supranationalReservePool.findUnique({
      where: { poolId },
      include: {
        stressTests: {
          orderBy: { testedAt: 'desc' },
          take: 10,
        },
      },
    });
  }

  /**
   * Get default commodity shock for region
   */
  private getDefaultCommodityShock(region: string): string {
    const defaults: Record<string, string> = {
      EU: 'S2',
      AU: 'S3',
      ASEAN: 'S1',
      GCC: 'S3',
      MERCOSUR: 'S4',
    };
    return defaults[region] || 'S2';
  }

  /**
   * Get default FX shock for region
   */
  private getDefaultFxShock(region: string): string {
    const defaults: Record<string, string> = {
      EU: 'F2',
      AU: 'F1',
      ASEAN: 'F3',
      GCC: 'F2',
      MERCOSUR: 'F4',
    };
    return defaults[region] || 'F2';
  }
}

export const gruReservePoolStressService = new GruReservePoolStressService();

