// ISRM Reserve Service
// Reserve composition across quantum/parallel/temporal states

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


export interface CreateReserveRequest {
  reserveName: string;
  classicalReserve: string;
  quantumReserve?: string;
  parallelReserve?: string;
  holographicReserve?: string;
  temporalReserve?: string;
}

export interface ReserveCompositionResult {
  reserveId: string;
  totalReserve: string;
  variance?: string;
  entropy?: string;
}

export class IsrmReserveService {
  /**
   * Create an infinite-state reserve
   */
  async createReserve(request: CreateReserveRequest): Promise<MultiverseReserve> {
    const reserveId = `ISRM-${uuidv4()}`;

    const classicalReserve = new Decimal(request.classicalReserve);
    const quantumReserve = request.quantumReserve ? new Decimal(request.quantumReserve) : null;
    const parallelReserve = request.parallelReserve ? new Decimal(request.parallelReserve) : null;
    const holographicReserve = request.holographicReserve ? new Decimal(request.holographicReserve) : null;
    const temporalReserve = request.temporalReserve ? new Decimal(request.temporalReserve) : null;

    // Calculate total reserve
    let totalReserve = classicalReserve;
    if (quantumReserve) totalReserve = totalReserve.plus(quantumReserve);
    if (parallelReserve) totalReserve = totalReserve.plus(parallelReserve);
    if (holographicReserve) totalReserve = totalReserve.plus(holographicReserve);
    if (temporalReserve) totalReserve = totalReserve.plus(temporalReserve);

    const reserve = await prisma.infiniteStateReserve.create({
      data: {
        reserveId,
        reserveName: request.reserveName,
        classicalReserve,
        quantumReserve,
        parallelReserve,
        holographicReserve,
        temporalReserve,
        totalReserve,
        status: 'active',
        calculatedAt: new Date(),
      },
    });

    return {
      reserveId: reserve.reserveId,
      reserveName: reserve.reserveName,
      classicalReserve: reserve.classicalReserve.toString(),
      quantumReserve: reserve.quantumReserve?.toString(),
      parallelReserve: reserve.parallelReserve?.toString(),
      holographicReserve: reserve.holographicReserve?.toString(),
      temporalReserve: reserve.temporalReserve?.toString(),
      totalReserve: reserve.totalReserve.toString(),
      variance: reserve.variance?.toString(),
      entropy: reserve.entropy?.toString(),
      status: reserve.status,
    };
  }

  /**
   * Recalculate reserve composition
   */
  async recalculateReserve(reserveId: string): Promise<ReserveCompositionResult> {
    const reserve = await prisma.infiniteStateReserve.findUnique({
      where: { reserveId },
      include: {
        quantumStates: true,
        parallelBranches: true,
        temporalFutures: true,
      },
    });

    if (!reserve) {
      throw new Error(`Reserve not found: ${reserveId}`);
    }

    // Recalculate total from all components
    let totalReserve = reserve.classicalReserve;
    if (reserve.quantumReserve) totalReserve = totalReserve.plus(reserve.quantumReserve);
    if (reserve.parallelReserve) totalReserve = totalReserve.plus(reserve.parallelReserve);
    if (reserve.holographicReserve) totalReserve = totalReserve.plus(reserve.holographicReserve);
    if (reserve.temporalReserve) totalReserve = totalReserve.plus(reserve.temporalReserve);

    // Calculate variance across states
    const reserves = [
      reserve.classicalReserve,
      reserve.quantumReserve || new Decimal(0),
      reserve.parallelReserve || new Decimal(0),
      reserve.holographicReserve || new Decimal(0),
      reserve.temporalReserve || new Decimal(0),
    ].filter(r => !r.equals(0));

    let variance = new Decimal(0);
    if (reserves.length > 1) {
      const mean = totalReserve.div(reserves.length);
      const sumSquaredDiffs = reserves.reduce((sum, r) => {
        const diff = r.minus(mean);
        return sum.plus(diff.pow(2));
      }, new Decimal(0));
      variance = sumSquaredDiffs.div(reserves.length);
    }

    // Update reserve
    await prisma.infiniteStateReserve.update({
      where: { reserveId },
      data: {
        totalReserve,
        variance,
        calculatedAt: new Date(),
      },
    });

    return {
      reserveId: reserve.reserveId,
      totalReserve: totalReserve.toString(),
      variance: variance.toString(),
      entropy: reserve.entropy?.toString(),
    };
  }

  /**
   * Get reserve by ID
   */
  async getReserve(reserveId: string): Promise<MultiverseReserve | null> {
    const reserve = await prisma.infiniteStateReserve.findUnique({
      where: { reserveId },
      include: {
        quantumStates: true,
        parallelBranches: true,
        temporalFutures: true,
      },
    });

    if (!reserve) {
      return null;
    }

    return {
      reserveId: reserve.reserveId,
      reserveName: reserve.reserveName,
      classicalReserve: reserve.classicalReserve.toString(),
      quantumReserve: reserve.quantumReserve?.toString(),
      parallelReserve: reserve.parallelReserve?.toString(),
      holographicReserve: reserve.holographicReserve?.toString(),
      temporalReserve: reserve.temporalReserve?.toString(),
      totalReserve: reserve.totalReserve.toString(),
      variance: reserve.variance?.toString(),
      entropy: reserve.entropy?.toString(),
      status: reserve.status,
    };
  }
}

