// DBIS Singularity-Grade Liquidity Engine - Auto-Generation Service
// Auto-generates liquidity within conservation limits

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { Decimal } from '@prisma/client/runtime/library';
import { sgleEngineService } from './sgle-engine.service';


export interface LiquidityGenerationRequest {
  gapId: string;
  maxGeneration: number;
  conservationLimit: number;
}

export interface GenerationResult {
  generationId: string;
  gapId: string;
  generatedAmount: Decimal;
  withinLimits: boolean;
  generationType: string;
}

export class SgleGenerationService {
  /**
   * Auto-generate liquidity within conservation limits
   * if liquidity_gap_detected: auto_generate_liquidity(within_conservation_limits)
   */
  async autoGenerateLiquidity(
    gapId: string,
    conservationLimit: number = 0.1
  ): Promise<GenerationResult> {
    const generationId = `SGLE-GEN-${uuidv4()}`;

    const gap = await prisma.liquidity_gaps.findUnique({
      where: { gapId },
      include: {
        projection: true,
      },
    });

    if (!gap) {
      throw new Error(`Liquidity gap not found: ${gapId}`);
    }

    const gapAmount = gap.gapAmount.abs();
    const limitDecimal = new Decimal(conservationLimit);

    // Calculate generation amount (limited by conservation constraint)
    // Generation cannot exceed gap amount * conservation limit
    const maxGeneration = gapAmount.times(limitDecimal);
    const generatedAmount = maxGeneration;

    const withinLimits = generatedAmount.lessThanOrEqualTo(maxGeneration);

    // Create liquidity generation record
    const liquidity = await prisma.singularity_liquidity.create({
      data: {
        liquidityId: `SGLE-LIQ-${uuidv4()}`,
        generationId,
        gapId,
        liquidityAmount: generatedAmount,
        generationType: 'auto',
        conservationLimit: limitDecimal,
        withinLimits,
        status: 'active',
      },
    });

    // Update gap status
    await prisma.liquidity_gaps.update({
      where: { gapId },
      data: {
        status: 'addressed',
        updatedAt: new Date(),
      },
    });

    return {
      generationId,
      gapId,
      generatedAmount,
      withinLimits,
      generationType: 'auto',
    };
  }

  /**
   * Detect liquidity gaps and auto-generate
   */
  async detectAndGenerateLiquidity(conservationLimit: number = 0.1) {
    const projections = await sgleEngineService.getProjectionsWithGaps();

    const results: GenerationResult[] = [];

    for (const projection of projections) {
      // Find or create gap
      let gap = await prisma.liquidity_gaps.findFirst({
        where: {
          projectionId: projection.projectionId,
          status: 'detected',
        },
      });

      if (!gap) {
        const gapId = `SGLE-GAP-${uuidv4()}`;
        gap = await prisma.liquidity_gaps.create({
          data: {
            gapId,
            projectionId: projection.projectionId,
            gapAmount: projection.liquidityGap,
            status: 'detected',
          },
        });
      }

      // Auto-generate liquidity
      const result = await this.autoGenerateLiquidity(gap.gapId, conservationLimit);
      results.push(result);
    }

    return results;
  }

  /**
   * Get generation by ID
   */
  async getGeneration(generationId: string) {
    return await prisma.singularity_liquidity.findFirst({
      where: { generationId },
      include: {
        gap: {
          include: {
            projection: true,
          },
        },
      },
    });
  }

  /**
   * Get all auto-generated liquidity
   */
  async getAutoGeneratedLiquidity() {
    return await prisma.singularity_liquidity.findMany({
      where: {
        generationType: 'auto',
        status: 'active',
      },
      orderBy: { createdAt: 'desc' },
    });
  }
}

export const sgleGenerationService = new SgleGenerationService();

