// Sanctions Synchronization Service

import { Prisma } from '@prisma/client';
import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { logger } from '@/infrastructure/monitoring/logger';


export class SanctionsSyncService {
  /**
   * Synchronize sanctions lists from sovereign sources
   */
  async syncSanctionsLists(sovereignBankId?: string): Promise<void> {
    logger.info('Starting sanctions list synchronization');

    // In production, this would fetch from OFAC, EU, UN, etc.
    // For now, we'll sync from existing sanctions lists in the database

    const existingLists = await prisma.sanctionsList.findMany({
      where: { status: 'active' },
      distinct: ['entityName', 'listSource'],
    });

    // Create unified global sanctions list entries
    for (const list of existingLists) {
      await prisma.globalSanctionsList.upsert({
        where: {
          entityName_listSource: {
            entityName: list.entityName,
            listSource: list.listSource,
          },
        },
        create: {
          id: uuidv4(),
          entityName: list.entityName,
          entityType: list.entityType,
          listSource: list.listSource,
          listId: list.listId,
          country: this.extractCountry(list.metadata),
          status: 'active',
          effectiveDate: list.effectiveDate,
          expiryDate: list.expiryDate,
          metadata: list.metadata as Prisma.InputJsonValue as Prisma.InputJsonValue,
        },
        update: {
          status: 'active',
          effectiveDate: list.effectiveDate,
          expiryDate: list.expiryDate,
          metadata: list.metadata as Prisma.InputJsonValue as Prisma.InputJsonValue,
        },
      });
    }

    logger.info(`Synchronized ${existingLists.length} sanctions list entries`);
  }

  /**
   * Search global sanctions list
   */
  async searchSanctions(entityName: string, threshold: number = 0.93): Promise<any[]> {
    // Fuzzy match against global sanctions list
    const matches = await prisma.globalSanctionsList.findMany({
      where: {
        status: 'active',
        OR: [
          {
            entityName: {
              contains: entityName,
              mode: 'insensitive',
            },
          },
        ],
      },
    });

    // Calculate match scores (simplified)
    const scoredMatches = matches.map((match) => ({
      ...match,
      matchScore: this.calculateMatchScore(entityName, match.entityName),
    }));

    // Filter by threshold
    return scoredMatches.filter((m) => m.matchScore >= threshold);
  }

  /**
   * Calculate fuzzy match score
   */
  private calculateMatchScore(name1: string, name2: string): number {
    // Simplified Levenshtein-based similarity
    const longer = name1.length > name2.length ? name1 : name2;
    const shorter = name1.length > name2.length ? name2 : name1;

    if (longer.length === 0) {
      return 1.0;
    }

    const distance = this.levenshteinDistance(longer.toLowerCase(), shorter.toLowerCase());
    return (longer.length - distance) / longer.length;
  }

  /**
   * Levenshtein distance
   */
  private levenshteinDistance(str1: string, str2: string): number {
    const matrix: number[][] = [];

    for (let i = 0; i <= str2.length; i++) {
      matrix[i] = [i];
    }

    for (let j = 0; j <= str1.length; j++) {
      matrix[0][j] = j;
    }

    for (let i = 1; i <= str2.length; i++) {
      for (let j = 1; j <= str1.length; j++) {
        if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
          matrix[i][j] = matrix[i - 1][j - 1];
        } else {
          matrix[i][j] = Math.min(
            matrix[i - 1][j - 1] + 1,
            matrix[i][j - 1] + 1,
            matrix[i - 1][j] + 1
          );
        }
      }
    }

    return matrix[str2.length][str1.length];
  }

  /**
   * Extract country from metadata
   */
  private extractCountry(metadata: any): string | null {
    if (!metadata || typeof metadata !== 'object') {
      return null;
    }
    return metadata.country || metadata.nationality || null;
  }

  /**
   * Get all active sanctions
   */
  async getAllActiveSanctions() {
    return prisma.globalSanctionsList.findMany({
      where: { status: 'active' },
      orderBy: { entityName: 'asc' },
    });
  }
}

export const sanctionsSyncService = new SanctionsSyncService();

