// DBIS Global Multiversal Monetary Theory - Conversion Service
// Cross-reality unit conversion

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


export interface CreateConversionRequest {
  sourceUnitId: string;
  targetUnitId: string;
  conversionRate: number;
  conversionFormula?: Record<string, unknown>;
  confidenceLevel?: number;
}

export class GmmtConversionService {
  /**
   * Create monetary unit conversion
   */
  async createConversion(request: CreateConversionRequest) {
    // Verify units exist
    const sourceUnit = await prisma.multiversalMonetaryUnit.findUnique({
      where: { unitId: request.sourceUnitId },
    });

    if (!sourceUnit) {
      throw new Error(`Source unit not found: ${request.sourceUnitId}`);
    }

    const targetUnit = await prisma.multiversalMonetaryUnit.findUnique({
      where: { unitId: request.targetUnitId },
    });

    if (!targetUnit) {
      throw new Error(`Target unit not found: ${request.targetUnitId}`);
    }

    const conversionId = `CONV-${uuidv4()}`;

    const conversion = await prisma.monetaryUnitConversion.create({
      data: {
        conversionId,
        sourceUnitId: request.sourceUnitId,
        targetUnitId: request.targetUnitId,
        conversionRate: new Decimal(request.conversionRate),
        conversionFormula: request.conversionFormula || null,
        confidenceLevel: new Decimal(request.confidenceLevel || 1.0),
        status: 'active',
        validFrom: new Date(),
      },
    });

    return conversion;
  }

  /**
   * Convert amount between units
   */
  async convertAmount(sourceUnitId: string, targetUnitId: string, amount: number) {
    const conversion = await prisma.monetaryUnitConversion.findFirst({
      where: {
        sourceUnitId,
        targetUnitId,
        status: 'active',
        validTo: null,
      },
      orderBy: { validFrom: 'desc' },
    });

    if (!conversion) {
      throw new Error(`No conversion found from ${sourceUnitId} to ${targetUnitId}`);
    }

    const sourceAmount = new Decimal(amount);
    const convertedAmount = sourceAmount.times(conversion.conversionRate);

    return {
      sourceAmount: amount,
      targetAmount: convertedAmount.toNumber(),
      conversionRate: conversion.conversionRate.toNumber(),
      confidenceLevel: conversion.confidenceLevel.toNumber(),
      conversionId: conversion.conversionId,
    };
  }

  /**
   * Get conversion by ID
   */
  async getConversion(conversionId: string) {
    return await prisma.monetaryUnitConversion.findUnique({
      where: { conversionId },
      include: {
        sourceUnit: true,
        targetUnit: true,
      },
    });
  }

  /**
   * Get all conversions for a unit
   */
  async getConversionsForUnit(unitId: string) {
    const asSource = await prisma.monetaryUnitConversion.findMany({
      where: {
        sourceUnitId: unitId,
        status: 'active',
      },
      include: {
        targetUnit: true,
      },
    });

    const asTarget = await prisma.monetaryUnitConversion.findMany({
      where: {
        targetUnitId: unitId,
        status: 'active',
      },
      include: {
        sourceUnit: true,
      },
    });

    return {
      asSource,
      asTarget,
    };
  }

  /**
   * Invalidate conversion
   */
  async invalidateConversion(conversionId: string) {
    return await prisma.monetaryUnitConversion.update({
      where: { conversionId },
      data: {
        status: 'inactive',
        validTo: new Date(),
      },
    });
  }
}

export const gmmtConversionService = new GmmtConversionService();

