// ML Enhancement Service for WAPL

import prisma from '@/shared/database/prisma';
import { PatternMatch } from './types';
import { logger } from '@/infrastructure/monitoring/logger';


export class MLEnhancementService {
  /**
   * Enhance pattern matching with ML (graph embeddings, anomaly detection)
   */
  async enhancePatternMatching(
    transactionId: string,
    patternMatches: PatternMatch[]
  ): Promise<PatternMatch[]> {
    // Apply graph embeddings
    const graphEmbeddings = await this.calculateGraphEmbeddings(transactionId);

    // Apply anomaly detection
    const anomalyScore = await this.detectAnomalies(transactionId);

    // Enhance match scores
    const enhancedMatches = patternMatches.map((match) => {
      let enhancedScore = match.matchScore;

      // Boost score if graph embeddings indicate clustering
      if (graphEmbeddings.clusterScore > 0.7) {
        enhancedScore = Math.min(1.0, enhancedScore + 0.2);
      }

      // Boost score if anomaly detected
      if (anomalyScore > 0.8) {
        enhancedScore = Math.min(1.0, enhancedScore + 0.15);
      }

      return {
        ...match,
        matchScore: enhancedScore,
      };
    });

    logger.info(`Enhanced ${enhancedMatches.length} pattern matches with ML`, {
      transactionId,
    });

    return enhancedMatches;
  }

  /**
   * Calculate graph embeddings for transaction
   */
  private async calculateGraphEmbeddings(transactionId: string): Promise<{
    clusterScore: number;
    embedding: number[];
  }> {
    // Simplified graph embedding calculation
    // In production, use actual graph neural networks

    // Get transaction and related entities
    const transaction = await prisma.ledger_entries.findUnique({
      where: { id: transactionId },
      include: {
        bank_accounts_ledger_entries_debitAccountIdTobank_accounts: true,
        bank_accounts_ledger_entries_creditAccountIdTobank_accounts: true,
      },
    });

    if (!transaction) {
      return { clusterScore: 0, embedding: [] };
    }

    // Calculate simple clustering score based on transaction patterns
    const relatedTransactions = await prisma.ledger_entries.findMany({
      where: {
        OR: [
          { debitAccountId: transaction.debitAccountId },
          { creditAccountId: transaction.creditAccountId },
        ],
        createdAt: {
          gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
        },
      },
      take: 10,
    });

    // Cluster score based on transaction frequency
    const clusterScore = Math.min(1.0, relatedTransactions.length / 10);

    return {
      clusterScore,
      embedding: [clusterScore, relatedTransactions.length],
    };
  }

  /**
   * Detect anomalies using statistical methods
   */
  private async detectAnomalies(transactionId: string): Promise<number> {
    // Simplified anomaly detection
    // In production, use actual ML models

    const transaction = await prisma.ledger_entries.findUnique({
      where: { id: transactionId },
    });

    if (!transaction) {
      return 0;
    }

    // Get historical transactions for comparison
    const historicalTransactions = await prisma.ledger_entries.findMany({
      where: {
        OR: [
          { debitAccountId: transaction.debitAccountId },
          { creditAccountId: transaction.creditAccountId },
        ],
        createdAt: {
          gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
          lt: transaction.createdAt,
        },
      },
    });

    if (historicalTransactions.length === 0) {
      return 0.5; // Moderate anomaly if no history
    }

    // Calculate average amount
    const avgAmount = historicalTransactions.reduce(
      (sum, tx) => sum + Number(tx.amount),
      0
    ) / historicalTransactions.length;

    const currentAmount = Number(transaction.amount);

    // Calculate anomaly score based on deviation
    const deviation = Math.abs(currentAmount - avgAmount) / (avgAmount || 1);
    const anomalyScore = Math.min(1.0, deviation / 2);

    return anomalyScore;
  }

  /**
   * Apply behavioral clustering
   */
  async applyBehavioralClustering(entityId: string): Promise<{
    clusterId: string;
    riskLevel: 'LOW' | 'MEDIUM' | 'HIGH';
  }> {
    // Simplified behavioral clustering
    // In production, use actual clustering algorithms

    const transactions = await prisma.ledger_entries.findMany({
      where: {
        OR: [
          { bank_accounts_ledger_entries_debitAccountIdTobank_accounts: { sovereignBankId: entityId } },
          { bank_accounts_ledger_entries_creditAccountIdTobank_accounts: { sovereignBankId: entityId } },
        ],
        createdAt: {
          gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
        },
      },
      take: 100,
    });

    // Calculate risk level based on transaction patterns
    const transactionCount = transactions.length;
    let riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' = 'LOW';

    if (transactionCount > 50) {
      riskLevel = 'HIGH';
    } else if (transactionCount > 20) {
      riskLevel = 'MEDIUM';
    }

    return {
      clusterId: `CLUSTER-${entityId}`,
      riskLevel,
    };
  }
}

export const mlEnhancementService = new MLEnhancementService();

