// UDFO Asset Ontology Service - Domain 1: Assets

import prisma from '@/shared/database/prisma';
import { AssetType, UDFOAsset } from './types';
import { v4 as uuidv4 } from 'uuid';
import { logger } from '@/infrastructure/monitoring/logger';


export class AssetOntologyService {
  /**
   * Get asset definition by type
   */
  async getAssetByType(assetType: AssetType): Promise<UDFOAsset | null> {
    const asset = await prisma.udfo_assets.findFirst({
      where: { assetType },
    });

    if (!asset) {
      return null;
    }

    return this.mapToUDFOAsset(asset);
  }

  /**
   * Get asset definition by code
   */
  async getAssetByCode(code: string): Promise<UDFOAsset | null> {
    const asset = await prisma.udfo_assets.findFirst({
      where: { code },
    });

    if (!asset) {
      return null;
    }

    return this.mapToUDFOAsset(asset);
  }

  /**
   * Create or update asset definition
   */
  async upsertAsset(asset: Partial<UDFOAsset>): Promise<UDFOAsset> {
    const assetId = asset.id || `UDFO-ASSET-${uuidv4()}`;

    const upserted = await prisma.udfo_assets.upsert({
      where: { id: assetId },
      create: {
        id: assetId,
        assetType: asset.assetType!,
        code: asset.code!,
        name: asset.name!,
        definition: asset.definition!,
        properties: asset.properties || {},
        metadata: asset.metadata || {},
      },
      update: {
        assetType: asset.assetType,
        code: asset.code,
        name: asset.name,
        definition: asset.definition,
        properties: asset.properties,
        metadata: asset.metadata,
      },
    });

    logger.info(`Upserted UDFO asset: ${assetId}`, { assetType: asset.assetType });

    return this.mapToUDFOAsset(upserted);
  }

  /**
   * Initialize default asset definitions
   */
  async initializeDefaultAssets(): Promise<void> {
    const defaultAssets: Partial<UDFOAsset>[] = [
      {
        assetType: AssetType.FIAT,
        code: 'FIAT',
        name: 'Fiat Currency',
        definition: 'Traditional government-issued currency',
        properties: {
          issuer: 'sovereign',
          backing: 'government_guarantee',
        },
      },
      {
        assetType: AssetType.CBDC,
        code: 'CBDC',
        name: 'Central Bank Digital Currency',
        definition: 'Digital currency issued by a central bank',
        properties: {
          issuer: 'central_bank',
          backing: 'sovereign_reserve',
          type: 'retail_or_wholesale',
        },
      },
      {
        assetType: AssetType.SSU,
        code: 'SSU',
        name: 'Synthetic Settlement Unit',
        definition: 'Stabilized cross-border settlement asset (40% currency, 30% commodity, 20% CBDC, 10% LAM)',
        properties: {
          type: 'synthetic',
          stability: 'high',
          backing: 'multi_asset_basket',
          composition: {
            currency: 0.4,
            commodity: 0.3,
            cbdc: 0.2,
            lam: 0.1,
          },
        },
      },
      {
        assetType: AssetType.COMMODITY,
        code: 'COMMODITY',
        name: 'Commodity',
        definition: 'Physical or digital commodity token',
        properties: {
          type: 'physical_or_digital',
          backing: 'physical_reserve',
        },
      },
      {
        assetType: AssetType.SECURITY,
        code: 'SECURITY',
        name: 'Security Token',
        definition: 'Tokenized security or financial instrument',
        properties: {
          type: 'tokenized',
          backing: 'underlying_security',
        },
      },
    ];

    for (const asset of defaultAssets) {
      await this.upsertAsset(asset);
    }

    logger.info('Initialized default UDFO asset definitions');
  }

  /**
   * Get all assets
   */
  async getAllAssets(): Promise<UDFOAsset[]> {
    const assets = await prisma.udfo_assets.findMany({
      orderBy: { assetType: 'asc' },
    });

    return assets.map((a) => this.mapToUDFOAsset(a));
  }

  private mapToUDFOAsset(asset: any): UDFOAsset {
    return {
      id: asset.id,
      assetType: asset.assetType as AssetType,
      code: asset.code,
      name: asset.name,
      definition: asset.definition,
      properties: asset.properties as Record<string, unknown>,
      metadata: asset.metadata as Record<string, unknown> | undefined,
    };
  }
}

export const assetOntologyService = new AssetOntologyService();

