// DBIS Unified Dimensional Arbitrage Engine - Compression Protocol
// Restores dimensional equilibrium when arbitrage delta exceeds tolerance

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { udaeEngineService } from './udae-engine.service';
import { udaeRebalanceService } from './udae-rebalance.service';


export interface CompressionResult {
  compressed: boolean;
  arbitrageId: string;
  originalDelta: number;
  compressedDelta: number;
  rebalanceExecuted: boolean;
}

export class UdaeCompressionService {
  /**
   * Check if arbitrage delta exceeds tolerance and trigger compression
   * if arbitrage_delta > tolerance: execute_dimensional_rebalance()
   */
  async checkAndCompress(arbitrageId: string, tolerance: number = 0.01): Promise<CompressionResult> {
    const arbitrage = await prisma.dimensionalArbitrage.findUnique({
      where: { arbitrageId },
    });

    if (!arbitrage) {
      throw new Error(`Arbitrage calculation not found: ${arbitrageId}`);
    }

    const delta = arbitrage.arbitrageDelta;
    const toleranceDecimal = new Decimal(tolerance);

    if (delta.abs().greaterThan(toleranceDecimal)) {
      // Execute dimensional rebalance
      const rebalance = await udaeRebalanceService.executeDimensionalRebalance(arbitrageId);

      // Update arbitrage status
      await prisma.dimensionalArbitrage.update({
        where: { arbitrageId },
        data: {
          status: 'compressed',
          updatedAt: new Date(),
        },
      });

      // Calculate compressed delta (should be within tolerance after rebalance)
      const compressedDelta = delta.minus(rebalance.adjustmentAmount);

      return {
        compressed: true,
        arbitrageId,
        originalDelta: delta.toNumber(),
        compressedDelta: compressedDelta.toNumber(),
        rebalanceExecuted: true,
      };
    }

    return {
      compressed: false,
      arbitrageId,
      originalDelta: delta.toNumber(),
      compressedDelta: delta.toNumber(),
      rebalanceExecuted: false,
    };
  }

  /**
   * Compress all arbitrage opportunities exceeding tolerance
   */
  async compressAllArbitrageOpportunities(tolerance: number = 0.01) {
    const opportunities = await udaeEngineService.getArbitrageOpportunities();

    const results: CompressionResult[] = [];

    for (const opp of opportunities) {
      const result = await this.checkAndCompress(opp.arbitrageId, tolerance);
      results.push(result);
    }

    return results;
  }

  /**
   * Get compression history for arbitrage
   */
  async getCompressionHistory(arbitrageId: string) {
    const arbitrage = await prisma.dimensionalArbitrage.findUnique({
      where: { arbitrageId },
      include: {
        rebalances: {
          orderBy: { createdAt: 'desc' },
        },
      },
    });

    return arbitrage?.rebalances || [];
  }
}

export const udaeCompressionService = new UdaeCompressionService();

