// PEP Graph Service

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


export class PEPGraphService {
  /**
   * Add PEP node to graph
   */
  async addPEPNode(node: Partial<PEPGraphNode>): Promise<PEPGraphNode> {
    const pepNode = await prisma.pEPGraphNode.upsert({
      where: { entityId: node.entityId! },
      create: {
        id: uuidv4(),
        entityId: node.entityId!,
        entityName: node.entityName!,
        pepType: node.pepType || 'UNKNOWN',
        country: node.country || 'UNKNOWN',
        position: node.position || '',
        riskLevel: node.riskLevel || 'MEDIUM',
      },
      update: {
        entityName: node.entityName,
        pepType: node.pepType,
        country: node.country,
        position: node.position,
        riskLevel: node.riskLevel,
      },
    });

    logger.info(`Added PEP node: ${pepNode.entityId}`);

    return this.mapToPEPNode(pepNode);
  }

  /**
   * Add PEP relationship edge
   */
  async addPEPEdge(edge: Partial<PEPGraphEdge>): Promise<PEPGraphEdge> {
    const pepEdge = await prisma.pEPGraphEdge.create({
      data: {
        id: uuidv4(),
        fromNodeId: edge.fromNodeId!,
        toNodeId: edge.toNodeId!,
        relationshipType: edge.relationshipType || 'UNKNOWN',
        strength: edge.strength || 0.5,
      },
    });

    logger.info(`Added PEP edge: ${pepEdge.id}`);

    return this.mapToPEPEdge(pepEdge);
  }

  /**
   * Find PEP connections for entity
   */
  async findPEPConnections(entityId: string, maxDepth: number = 2): Promise<PEPGraphNode[]> {
    const visited = new Set<string>();
    const connections: PEPGraphNode[] = [];

    const traverse = async (currentEntityId: string, depth: number) => {
      if (depth > maxDepth || visited.has(currentEntityId)) {
        return;
      }

      visited.add(currentEntityId);

      // Find all edges from this node
      const edges = await prisma.pEPGraphEdge.findMany({
        where: {
          OR: [
            { fromNodeId: currentEntityId },
            { toNodeId: currentEntityId },
          ],
        },
      });

      for (const edge of edges) {
        const connectedEntityId = edge.fromNodeId === currentEntityId
          ? edge.toNodeId
          : edge.fromNodeId;

        if (!visited.has(connectedEntityId)) {
          const node = await prisma.pEPGraphNode.findUnique({
            where: { entityId: connectedEntityId },
          });

          if (node) {
            connections.push(this.mapToPEPNode(node));
            await traverse(connectedEntityId, depth + 1);
          }
        }
      }
    };

    await traverse(entityId, 0);

    return connections;
  }

  /**
   * Check if entity is PEP
   */
  async isPEP(entityId: string): Promise<boolean> {
    const node = await prisma.pEPGraphNode.findUnique({
      where: { entityId },
    });

    return !!node;
  }

  /**
   * Get PEP node by entity ID
   */
  async getPEPNode(entityId: string): Promise<PEPGraphNode | null> {
    const node = await prisma.pEPGraphNode.findUnique({
      where: { entityId },
    });

    if (!node) {
      return null;
    }

    return this.mapToPEPNode(node);
  }

  private mapToPEPNode(node: any): PEPGraphNode {
    return {
      id: node.id,
      entityId: node.entityId,
      entityName: node.entityName,
      pepType: node.pepType,
      country: node.country,
      position: node.position,
      riskLevel: node.riskLevel,
    };
  }

  private mapToPEPEdge(edge: any): PEPGraphEdge {
    return {
      id: edge.id,
      fromNodeId: edge.fromNodeId,
      toNodeId: edge.toNodeId,
      relationshipType: edge.relationshipType,
      strength: edge.strength,
    };
  }
}

export const pepGraphService = new PEPGraphService();

