// GRU Omega Layer Reconciliation Service
// Post-stress reconciliation across multi-reality states

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 { gruTemporalStressService } from './gru-temporal-stress.service';


export interface TimelineDeviation {
  layer: string;
  preStressDeviation: Decimal;
  postStressDeviation: Decimal;
  deviation: Decimal;
}

export interface OmegaLayerMatrix {
  layer: string;
  preStressDeviation: Decimal;
  postStressDeviation: Decimal;
  status: string;
}

export class GruOmegaReconciliationService {
  /**
   * Reconcile all timeline variants after stress
   */
  async reconcilePostStress(testId: string): Promise<OmegaLayerMatrix[]> {
    logger.info('GRU Omega Reconciliation: Reconciling post-stress', { testId });

    // Get stress test
    const test = await prisma.gruStressTest.findUnique({
      where: { testId },
      include: {
        results: true,
      },
    });

    if (!test) {
      throw new Error(`Stress test not found: ${testId}`);
    }

    // Generate Ω-Layer stability matrix
    const stabilityMatrix = await gruTemporalStressService.runOmegaLayerStabilityTest();
    const matrixData = stabilityMatrix.data as OmegaLayerMatrix[];

    // Create reconciliation records for each layer
    const reconciliations: any[] = [];

    for (const layerData of matrixData) {
      const reconciliationId = `OMEGA-RECON-${uuidv4()}`;
      const reconciliation = await prisma.gruOmegaLayerReconciliation.create({
        data: {
          reconciliationId,
          testId: test.id,
          layer: layerData.layer,
          preStressDeviation: new Decimal(layerData.preStressDeviation),
          postStressDeviation: new Decimal(layerData.postStressDeviation),
          correctionStatus: layerData.status,
          reconciliationData: {
            layer: layerData.layer,
            preStressDeviation: layerData.preStressDeviation,
            postStressDeviation: layerData.postStressDeviation,
            status: layerData.status,
          },
          status: 'completed',
          reconciledAt: new Date(),
        },
      });

      reconciliations.push(reconciliation);
    }

    logger.info('GRU Omega Reconciliation: Post-stress reconciliation completed', {
      testId,
      layers: reconciliations.length,
    });

    return matrixData;
  }

  /**
   * Generate Ω-Layer stability matrix
   */
  async generateOmegaLayerMatrix(): Promise<OmegaLayerMatrix[]> {
    logger.info('GRU Omega Reconciliation: Generating Ω-Layer matrix');

    const stabilityMatrix = await gruTemporalStressService.runOmegaLayerStabilityTest();
    return stabilityMatrix.data as OmegaLayerMatrix[];
  }

  /**
   * Merge deviations from different timelines
   */
  async mergeTimelineDeviations(
    deviations: TimelineDeviation[]
  ): Promise<OmegaLayerMatrix> {
    logger.info('GRU Omega Reconciliation: Merging timeline deviations', {
      deviationsCount: deviations.length,
    });

    // Calculate average pre-stress and post-stress deviations
    let totalPreStress = new Decimal(0);
    let totalPostStress = new Decimal(0);

    for (const deviation of deviations) {
      totalPreStress = totalPreStress.plus(deviation.preStressDeviation);
      totalPostStress = totalPostStress.plus(deviation.postStressDeviation);
    }

    const avgPreStress = totalPreStress.dividedBy(deviations.length);
    const avgPostStress = totalPostStress.dividedBy(deviations.length);

    // Determine correction status
    let status = 'stabilized';
    if (avgPostStress.isZero()) {
      status = 'fully_merged';
    } else if (avgPostStress.lessThan(2)) {
      status = 'corrected';
    } else if (avgPostStress.lessThan(5)) {
      status = 'harmonized';
    }

    return {
      layer: 'merged',
      preStressDeviation: avgPreStress,
      postStressDeviation: avgPostStress,
      status,
    };
  }

  /**
   * Get reconciliation by test ID
   */
  async getReconciliationsByTest(testId: string) {
    const test = await prisma.gruStressTest.findUnique({
      where: { testId },
    });

    if (!test) {
      throw new Error(`Stress test not found: ${testId}`);
    }

    return await prisma.gruOmegaLayerReconciliation.findMany({
      where: { testId: test.id },
      orderBy: { reconciledAt: 'desc' },
    });
  }

  /**
   * Get reconciliation by ID
   */
  async getReconciliation(reconciliationId: string) {
    return await prisma.gruOmegaLayerReconciliation.findUnique({
      where: { reconciliationId },
      include: {
        test: true,
      },
    });
  }

  /**
   * Get all reconciliations for a layer
   */
  async getReconciliationsByLayer(layer: string) {
    return await prisma.gruOmegaLayerReconciliation.findMany({
      where: { layer },
      orderBy: { reconciledAt: 'desc' },
    });
  }

  /**
   * Calculate reconciliation effectiveness
   */
  async calculateReconciliationEffectiveness(
    reconciliationId: string
  ): Promise<{
    effectiveness: Decimal;
    improvement: Decimal;
    status: string;
  }> {
    const reconciliation = await prisma.gruOmegaLayerReconciliation.findUnique({
      where: { reconciliationId },
    });

    if (!reconciliation) {
      throw new Error(`Reconciliation not found: ${reconciliationId}`);
    }

    // Calculate improvement percentage
    const improvement = reconciliation.preStressDeviation.gt(0)
      ? reconciliation.preStressDeviation
          .minus(reconciliation.postStressDeviation)
          .dividedBy(reconciliation.preStressDeviation)
          .times(100)
      : new Decimal(0);

    // Calculate effectiveness (inverse of post-stress deviation)
    const effectiveness = reconciliation.postStressDeviation.gt(0)
      ? new Decimal(100).minus(reconciliation.postStressDeviation)
      : new Decimal(100);

    return {
      effectiveness,
      improvement,
      status: reconciliation.correctionStatus,
    };
  }
}

export const gruOmegaReconciliationService = new GruOmegaReconciliationService();

