// STCE Valuation Service
// TCU value calculation with stability equation

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';
import { TemporalStabilityState } from '@/shared/types';
import { StceProjectionService } from './stce-projection.service';

const projectionService = new StceProjectionService();

export interface TcuValueResult {
  presentValue: string;
  futureWeight: string;
  retroFactor: string;
  ssuAnchor?: string;
  calculatedValue: string;
  stabilityScore?: string;
}

export class StceValuationService {
  /**
   * Calculate TCU value using stability equation:
   * TCU_value = present_value + future_weight - retro_factor + SSU_anchor
   */
  async calculateTcuValue(tcuId: string): Promise<TemporalStabilityState> {
    const tcu = await prisma.temporal_currency_units.findUnique({
      where: { tcuId },
    });

    if (!tcu) {
      throw new Error(`TCU not found: ${tcuId}`);
    }

    const presentValue = tcu.presentValue;

    // Calculate future_weight = projection(t+Δt)
    // Use standard time delta of 1 time unit for forward projection
    const forwardProj = await projectionService.calculateForwardProjection(
      tcuId,
      '1.0'
    );
    const futureWeight = new Decimal(forwardProj.projectedValue).minus(presentValue);

    // Calculate retro_factor = correction(t-Δt)
    // Use standard time delta of 1 time unit for retro correction
    const retroProj = await projectionService.calculateRetroCorrection(
      tcuId,
      '1.0'
    );
    const retroFactor = presentValue.minus(new Decimal(retroProj.projectedValue));

    // Get SSU anchor if available
    // For now, set to zero - would integrate with SSU system in production
    const ssuAnchor = new Decimal(0);

    // Calculate TCU value: present_value + future_weight - retro_factor + SSU_anchor
    const calculatedValue = presentValue
      .plus(futureWeight)
      .minus(retroFactor)
      .plus(ssuAnchor);

    // Calculate stability score (0-1, higher is more stable)
    const variance = futureWeight.abs().plus(retroFactor.abs());
    const stabilityScore = new Decimal(1).minus(
      variance.div(presentValue.mul(2)).min(new Decimal(1))
    );

    // Create stability state record
    const stateId = `TCU-STATE-${uuidv4()}`;
    const stabilityState = await prisma.temporal_stability_states.create({
      data: {
        stateId,
        tcuId,
        presentValue,
        futureWeight,
        retroFactor,
        ssuAnchor: ssuAnchor.equals(0) ? null : ssuAnchor,
        calculatedValue,
        stabilityScore,
        calculatedAt: new Date(),
      },
    });

    return {
      stateId: stabilityState.stateId,
      tcuId: stabilityState.tcuId,
      presentValue: stabilityState.presentValue.toString(),
      futureWeight: stabilityState.futureWeight.toString(),
      retroFactor: stabilityState.retroFactor.toString(),
      ssuAnchor: stabilityState.ssuAnchor?.toString(),
      calculatedValue: stabilityState.calculatedValue.toString(),
      stabilityScore: stabilityState.stabilityScore?.toString(),
      calculatedAt: stabilityState.calculatedAt,
    };
  }

  /**
   * Get current stability state for a TCU
   */
  async getCurrentStabilityState(
    tcuId: string
  ): Promise<TemporalStabilityState | null> {
    const state = await prisma.temporal_stability_states.findFirst({
      where: { tcuId },
      orderBy: { calculatedAt: 'desc' },
    });

    if (!state) {
      return null;
    }

    return {
      stateId: state.stateId,
      tcuId: state.tcuId,
      presentValue: state.presentValue.toString(),
      futureWeight: state.futureWeight.toString(),
      retroFactor: state.retroFactor.toString(),
      ssuAnchor: state.ssuAnchor?.toString(),
      calculatedValue: state.calculatedValue.toString(),
      stabilityScore: state.stabilityScore?.toString(),
      calculatedAt: state.calculatedAt,
    };
  }

  /**
   * Get stability history for a TCU
   */
  async getStabilityHistory(
    tcuId: string,
    limit = 100
  ): Promise<TemporalStabilityState[]> {
    const states = await prisma.temporal_stability_states.findMany({
      where: { tcuId },
      orderBy: { calculatedAt: 'desc' },
      take: limit,
    });

    return states.map((state) => ({
      stateId: state.stateId,
      tcuId: state.tcuId,
      presentValue: state.presentValue.toString(),
      futureWeight: state.futureWeight.toString(),
      retroFactor: state.retroFactor.toString(),
      ssuAnchor: state.ssuAnchor?.toString(),
      calculatedValue: state.calculatedValue.toString(),
      stabilityScore: state.stabilityScore?.toString(),
      calculatedAt: state.calculatedAt,
    }));
  }
}

