// UDFO Entity Ontology Service - Domain 2: Entities

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


export class EntityOntologyService {
  /**
   * Get entity definition by type
   */
  async getEntityByType(entityType: EntityType): Promise<UDFOEntity | null> {
    const entity = await prisma.uDFOEntity.findFirst({
      where: { entityType },
    });

    if (!entity) {
      return null;
    }

    return this.mapToUDFOEntity(entity);
  }

  /**
   * Get entity definition by identifier
   */
  async getEntityByIdentifier(identifier: string): Promise<UDFOEntity | null> {
    const entity = await prisma.uDFOEntity.findFirst({
      where: { identifier },
    });

    if (!entity) {
      return null;
    }

    return this.mapToUDFOEntity(entity);
  }

  /**
   * Create or update entity definition
   */
  async upsertEntity(entity: Partial<UDFOEntity>): Promise<UDFOEntity> {
    const entityId = entity.id || `UDFO-ENTITY-${uuidv4()}`;

    const upserted = await prisma.uDFOEntity.upsert({
      where: { id: entityId },
      create: {
        id: entityId,
        entityType: entity.entityType!,
        identifier: entity.identifier!,
        name: entity.name!,
        definition: entity.definition!,
        properties: entity.properties || {},
        metadata: entity.metadata || {},
      },
      update: {
        entityType: entity.entityType,
        identifier: entity.identifier,
        name: entity.name,
        definition: entity.definition,
        properties: entity.properties,
        metadata: entity.metadata,
      },
    });

    logger.info(`Upserted UDFO entity: ${entityId}`, { entityType: entity.entityType });

    return this.mapToUDFOEntity(upserted);
  }

  /**
   * Initialize default entity definitions
   */
  async initializeDefaultEntities(): Promise<void> {
    const defaultEntities: Partial<UDFOEntity>[] = [
      {
        entityType: EntityType.SCB,
        identifier: 'SCB',
        name: 'Sovereign Central Bank',
        definition: 'Central bank of a sovereign nation, member of DBIS',
        properties: {
          authority: 'sovereign',
          role: 'monetary_policy',
          membership: 'dbis',
        },
      },
      {
        entityType: EntityType.BANK,
        identifier: 'BANK',
        name: 'Private Bank',
        definition: 'Private commercial or investment bank',
        properties: {
          authority: 'licensed',
          role: 'financial_intermediation',
        },
      },
      {
        entityType: EntityType.INDIVIDUAL,
        identifier: 'INDIVIDUAL',
        name: 'Individual',
        definition: 'Individual person or wallet holder',
        properties: {
          authority: 'verified',
          role: 'retail_participant',
        },
      },
      {
        entityType: EntityType.INSTITUTION,
        identifier: 'INSTITUTION',
        name: 'Institution',
        definition: 'Corporate or institutional entity',
        properties: {
          authority: 'registered',
          role: 'institutional_participant',
        },
      },
      {
        entityType: EntityType.CONTRACT,
        identifier: 'CONTRACT',
        name: 'Smart Contract',
        definition: 'Deterministic smart contract on DBIS ledger',
        properties: {
          authority: 'code',
          role: 'automated_execution',
          determinism: 'required',
        },
      },
    ];

    for (const entity of defaultEntities) {
      await this.upsertEntity(entity);
    }

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

  /**
   * Get all entities
   */
  async getAllEntities(): Promise<UDFOEntity[]> {
    const entities = await prisma.uDFOEntity.findMany({
      orderBy: { entityType: 'asc' },
    });

    return entities.map((e) => this.mapToUDFOEntity(e));
  }

  private mapToUDFOEntity(entity: any): UDFOEntity {
    return {
      id: entity.id,
      entityType: entity.entityType as EntityType,
      identifier: entity.identifier,
      name: entity.name,
      definition: entity.definition,
      properties: entity.properties as Record<string, unknown>,
      metadata: entity.metadata as Record<string, unknown> | undefined,
    };
  }
}

export const entityOntologyService = new EntityOntologyService();

