// On-Ramp Service
// Real-world → Metaverse conversion: Fiat, CBDC, GRU, SSU → Virtual Currency
// Supplement B: MetaverseDubai Integration Framework

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 { dsezService } from '../d-sez/d-sez.service';
import { rampValidationService } from './ramp-validation.service';


export interface OnRampRequest {
  dsezId: string;
  metaverseNodeId: string;
  sourceType: 'fiat' | 'cbdc' | 'gru' | 'ssu';
  targetType: 'virtual_currency' | 'tokenized_asset';
  amount: string;
  currencyCode: string;
  sourceBankId?: string;
  destinationBankId?: string;
  metadata?: Record<string, unknown>;
}

export interface OnRampResult {
  rampId: string;
  status: string;
  exchangeRate?: number;
  virtualAmount?: string;
  validationHash?: string;
}

export class OnRampService {
  /**
   * Execute on-ramp: Real-world → Metaverse
   * Supports: Fiat, CBDC, GRU, SSU → Virtual Currency
   */
  async executeOnRamp(request: OnRampRequest): Promise<OnRampResult> {
    logger.info('On-Ramp: Executing on-ramp', { request });

    // Step 1: Verify D-SEZ exists and is active
    const dsez = await dsezService.getDsez(request.dsezId);
    if (!dsez || dsez.status !== 'active') {
      throw new Error(`D-SEZ not found or inactive: ${request.dsezId}`);
    }

    // Step 2: Verify liquidity flow is enabled
    if (!dsez.liquidityFlowEnabled) {
      throw new Error('Liquidity flow not enabled for this D-SEZ');
    }

    // Step 3: Calculate exchange rate
    const exchangeRate = await this.calculateExchangeRate(
      request.sourceType,
      request.targetType,
      request.currencyCode
    );

    // Step 4: Calculate virtual amount
    const virtualAmount = (
      parseFloat(request.amount) * exchangeRate
    ).toFixed(8);

    // Step 5: Validate transaction
    const validation = await rampValidationService.validateOnRamp({
      dsezId: request.dsezId,
      sourceType: request.sourceType,
      targetType: request.targetType,
      amount: request.amount,
      currencyCode: request.currencyCode,
      sourceBankId: request.sourceBankId,
    });

    if (!validation.validated) {
      throw new Error(`On-ramp validation failed: ${validation.reason}`);
    }

    // Step 6: Create ramp transaction
    const rampId = `ON-RAMP-${uuidv4()}`;
    const rampTransaction = await prisma.metaverseRampTransaction.create({
      data: {
        rampId,
        dsezId: request.dsezId,
        metaverseNodeId: request.metaverseNodeId,
        rampType: 'on_ramp',
        sourceType: request.sourceType,
        targetType: request.targetType,
        amount: new Decimal(request.amount),
        currencyCode: request.currencyCode,
        sourceBankId: request.sourceBankId || null,
        destinationBankId: request.destinationBankId || null,
        exchangeRate: new Decimal(exchangeRate),
        status: 'processing',
        complianceCheck: validation.complianceCheck,
        validationHash: validation.validationHash || null,
      },
    });

    // Step 7: Execute conversion (in a full implementation, this would interact with CBDC/GRU/SSU systems)
    // For now, we'll mark it as completed
    await prisma.metaverseRampTransaction.update({
      where: { rampId },
      data: {
        status: 'completed',
        processedAt: new Date(),
      },
    });

    logger.info('On-Ramp: On-ramp completed', {
      rampId,
      amount: request.amount,
      virtualAmount,
    });

    return {
      rampId,
      status: 'completed',
      exchangeRate,
      virtualAmount,
      validationHash: validation.validationHash,
    };
  }

  /**
   * Calculate exchange rate between source and target types
   */
  private async calculateExchangeRate(
    sourceType: string,
    targetType: string,
    currencyCode: string
  ): Promise<number> {
    // In a full implementation, this would:
    // 1. Query FX rates for fiat currencies
    // 2. Query CBDC conversion rates
    // 3. Query GRU conversion rates
    // 4. Query SSU conversion rates
    // 5. Apply metaverse-specific premiums/discounts

    // For now, return a default rate
    // Real-world to virtual typically has a 1:1 or slight premium
    const baseRate = 1.0;
    const metaversePremium = 0.02; // 2% premium for virtual currency

    return sourceType === 'fiat' || sourceType === 'cbdc'
      ? baseRate + metaversePremium
      : baseRate;
  }

  /**
   * Get on-ramp transaction by ID
   */
  async getOnRampTransaction(rampId: string) {
    return await prisma.metaverseRampTransaction.findUnique({
      where: { rampId },
      include: {
        dsez: true,
        node: true,
      },
    });
  }

  /**
   * Get on-ramp transactions for D-SEZ
   */
  async getOnRampTransactionsForDsez(dsezId: string) {
    return await prisma.metaverseRampTransaction.findMany({
      where: {
        dsezId,
        rampType: 'on_ramp',
      },
      orderBy: { createdAt: 'desc' },
    });
  }
}

export const onRampService = new OnRampService();

