// DBIS Volume XIV: DBIS Economic Entanglement Index (EEI)
// Measures how tightly economic states are entangled across realities

import prisma from '@/shared/database/prisma';
import type { Prisma } from '@prisma/client';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';


export interface MeasureEntanglementRequest {
  cohesionFactor?: number;
  divergencePressure?: number;
  quantumResonance?: number;
}

export class EeiService {
  /**
   * Measure Economic Entanglement Index
   * EEI = cohesion_factor - divergence_pressure + quantum_resonance
   */
  async measureEntanglement(
    request?: MeasureEntanglementRequest
  ): Promise<{
    entanglementId: string;
    eeiValue: number;
    stabilityLevel: string;
    components: {
      cohesionFactor: number;
      divergencePressure: number;
      quantumResonance: number;
    };
  }> {
    const entanglementId = `EEI-${uuidv4()}`;

    // Calculate or use provided components
    const cohesionFactor = await this.calculateCohesionFactor(
      request?.cohesionFactor
    );
    const divergencePressure = await this.calculateDivergencePressure(
      request?.divergencePressure
    );
    const quantumResonance = await this.calculateQuantumResonance(
      request?.quantumResonance
    );

    // Calculate EEI: cohesion_factor - divergence_pressure + quantum_resonance
    const eeiValue =
      cohesionFactor - divergencePressure + quantumResonance;

    // Determine stability level
    const stabilityLevel = this.determineStabilityLevel(eeiValue);

    // Create entanglement record
    const entanglement = await prisma.economic_entanglements.create({
      data: {
        id: uuidv4(),
        entanglementId,
        cohesionFactor: new Decimal(cohesionFactor),
        divergencePressure: new Decimal(divergencePressure),
        quantumResonance: new Decimal(quantumResonance),
        eeiValue: new Decimal(eeiValue),
        stabilityLevel,
        status: 'active',
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    // Create measurement records
    await prisma.entanglement_measurements.createMany({
      data: [
        {
          measurementId: `MEAS-${uuidv4()}`,
          entanglementId: entanglement.id,
          measurementType: 'cohesion',
          measurementValue: new Decimal(cohesionFactor),
          measurementDetails: {
            calculatedAt: new Date().toISOString(),
          } as unknown as object,
        },
        {
          measurementId: `MEAS-${uuidv4()}`,
          entanglementId: entanglement.id,
          measurementType: 'divergence',
          measurementValue: new Decimal(divergencePressure),
          measurementDetails: {
            calculatedAt: new Date().toISOString(),
          } as unknown as object,
        },
        {
          measurementId: `MEAS-${uuidv4()}`,
          entanglementId: entanglement.id,
          measurementType: 'quantum_resonance',
          measurementValue: new Decimal(quantumResonance),
          measurementDetails: {
            calculatedAt: new Date().toISOString(),
          } as unknown as object,
        },
      ],
    });

    return {
      entanglementId: entanglement.entanglementId,
      eeiValue,
      stabilityLevel,
      components: {
        cohesionFactor,
        divergencePressure,
        quantumResonance,
      },
    };
  }

  /**
   * Calculate cohesion factor
   */
  private async calculateCohesionFactor(
    provided?: number
  ): Promise<number> {
    if (provided !== undefined) {
      return provided;
    }

    // In production, this would analyze actual economic states across realities
    // For now, return a simulated value based on system state
    // Cohesion measures how well economic states align across realities

    // Simplified: check recent settlement coherence, identity alignment, etc.
    const recentSettlements = await prisma.holographic_settlements.count({
      where: {
        holographicCheck: true,
        createdAt: {
          gte: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
        },
      },
    });

    // Higher settlement count = higher cohesion (simplified)
    const baseCohesion = Math.min(1.0, recentSettlements / 100);

    // Add some randomness for simulation
    return baseCohesion + (Math.random() * 0.2 - 0.1);
  }

  /**
   * Calculate divergence pressure
   */
  private async calculateDivergencePressure(
    provided?: number
  ): Promise<number> {
    if (provided !== undefined) {
      return provided;
    }

    // Divergence pressure measures how much realities are pulling apart
    // In production, would analyze actual divergence metrics

    // Simplified: check for identity drift, contract disagreements, etc.
    const identityDrifts = await prisma.infinite_layer_identities.findMany({
      where: {
        identityDrift: {
          gt: new Decimal(0.01), // Significant drift
        },
      },
      take: 10,
    });

    // More drift = more divergence pressure
    const baseDivergence = Math.min(1.0, identityDrifts.length / 10);

    return baseDivergence + (Math.random() * 0.1);
  }

  /**
   * Calculate quantum resonance
   */
  private async calculateQuantumResonance(
    provided?: number
  ): Promise<number> {
    if (provided !== undefined) {
      return provided;
    }

    // Quantum resonance measures quantum coherence across realities
    // In production, would analyze actual quantum state coherence

    // Simplified: check for quantum states in contracts, assets, etc.
    const quantumContracts = await prisma.reality_spanning_contracts.count({
      where: {
        quantumStates: {
          not: Prisma.JsonNull,
        },
      },
    });

    // More quantum states = higher resonance (simplified)
    const baseResonance = Math.min(1.0, quantumContracts / 50);

    return baseResonance + (Math.random() * 0.15);
  }

  /**
   * Determine stability level based on EEI value
   */
  private determineStabilityLevel(eeiValue: number): string {
    if (eeiValue >= 0.8) {
      return 'very_high';
    } else if (eeiValue >= 0.6) {
      return 'high';
    } else if (eeiValue >= 0.4) {
      return 'medium';
    } else {
      return 'low';
    }
  }

  /**
   * Get latest entanglement measurement
   */
  async getLatestEntanglement(): Promise<{
    entanglementId: string;
    eeiValue: number;
    stabilityLevel: string;
    measuredAt: Date;
    components: {
      cohesionFactor: number;
      divergencePressure: number;
      quantumResonance: number;
    };
  } | null> {
    const entanglement = await prisma.economic_entanglements.findFirst({
      orderBy: {
        measurementTime: 'desc',
      },
      include: {
        entanglement_measurements: true,
      },
    });

    if (!entanglement) {
      return null;
    }

    const cohesion = entanglement.entanglement_measurements.find(
      (m) => m.measurementType === 'cohesion'
    );
    const divergence = entanglement.entanglement_measurements.find(
      (m) => m.measurementType === 'divergence'
    );
    const resonance = entanglement.entanglement_measurements.find(
      (m) => m.measurementType === 'quantum_resonance'
    );

    return {
      entanglementId: entanglement.entanglementId,
      eeiValue: entanglement.eeiValue.toNumber(),
      stabilityLevel: entanglement.stabilityLevel,
      measuredAt: entanglement.measurementTime,
      components: {
        cohesionFactor: cohesion?.measurementValue.toNumber() || 0,
        divergencePressure: divergence?.measurementValue.toNumber() || 0,
        quantumResonance: resonance?.measurementValue.toNumber() || 0,
      },
    };
  }

  /**
   * Get entanglement history
   */
  async getEntanglementHistory(limit: number = 100) {
    return prisma.economic_entanglements.findMany({
      orderBy: {
        measurementTime: 'desc',
      },
      take: limit,
      include: {
        entanglement_measurements: {
          orderBy: {
            measuredAt: 'desc',
          },
        },
      },
    });
  }

  /**
   * Get entanglement by ID
   */
  async getEntanglement(entanglementId: string) {
    return prisma.economic_entanglements.findUnique({
      where: { entanglementId },
      include: {
        entanglement_measurements: {
          orderBy: {
            measuredAt: 'desc',
          },
        },
      },
    });
  }

  /**
   * Analyze entanglement trends
   */
  async analyzeEntanglementTrends(days: number = 30): Promise<{
    trend: 'increasing' | 'decreasing' | 'stable';
    averageEei: number;
    stabilityDistribution: Record<string, number>;
  }> {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - days);

    const entanglements = await prisma.economic_entanglements.findMany({
      where: {
        measurementTime: {
          gte: cutoffDate,
        },
      },
      orderBy: {
        measurementTime: 'asc',
      },
    });

    if (entanglements.length === 0) {
      return {
        trend: 'stable',
        averageEei: 0,
        stabilityDistribution: {},
      };
    }

    // Calculate average
    const averageEei =
      entanglements.reduce(
        (sum, e) => sum + e.eeiValue.toNumber(),
        0
      ) / entanglements.length;

    // Determine trend
    const firstHalf = entanglements.slice(0, Math.floor(entanglements.length / 2));
    const secondHalf = entanglements.slice(Math.floor(entanglements.length / 2));

    const firstAvg =
      firstHalf.reduce((sum, e) => sum + e.eeiValue.toNumber(), 0) /
      firstHalf.length;
    const secondAvg =
      secondHalf.reduce((sum, e) => sum + e.eeiValue.toNumber(), 0) /
      secondHalf.length;

    let trend: 'increasing' | 'decreasing' | 'stable';
    const diff = secondAvg - firstAvg;
    if (Math.abs(diff) < 0.05) {
      trend = 'stable';
    } else if (diff > 0) {
      trend = 'increasing';
    } else {
      trend = 'decreasing';
    }

    // Calculate stability distribution
    const stabilityDistribution: Record<string, number> = {};
    for (const e of entanglements) {
      stabilityDistribution[e.stabilityLevel] =
        (stabilityDistribution[e.stabilityLevel] || 0) + 1;
    }

    // Normalize to percentages
    for (const key in stabilityDistribution) {
      stabilityDistribution[key] =
        (stabilityDistribution[key] / entanglements.length) * 100;
    }

    return {
      trend,
      averageEei,
      stabilityDistribution,
    };
  }
}

export const eeiService = new EeiService();

