import { logger } from '../../utils/logger';

export interface TransactionNode {
  id: string;
  type: 'USER' | 'WALLET' | 'MERCHANT';
  riskScore: number;
}

export interface TransactionEdge {
  from: string;
  to: string;
  amount: number;
  timestamp: Date;
}

/**
 * [BIZ_AUDIT_04] 基于图数据库的洗钱与欺诈检测 (Graph-based Fraud Detection)
 * @description 识别复杂交易网络中的异常模式，如环形转账、分拆洗钱 (Smurfing)、资金归集 (Clustering)
 */
export class FraudDetectionService {
  private static nodes: Map<string, TransactionNode> = new Map();
  private static edges: TransactionEdge[] = [];

  /**
   * 摄入新的交易记录并进行实时图谱分析
   */
  static async analyzeTransaction(tx: TransactionEdge): Promise<{ isSuspicious: boolean; reason?: string }> {
    logger.info(`[FraudDetection] Analyzing edge: ${tx.from} -> ${tx.to} with amount: ${tx.amount}`);

    this.edges.push(tx);
    
    // 1. 简单检测：环形转账 (Cycle Detection)
    if (this.detectCycle(tx.from, tx.to)) {
      logger.error(`[FraudDetection] CRITICAL: Potential money laundering cycle detected involving ${tx.from}`);
      return { isSuspicious: true, reason: 'Circular transaction pattern (Potential Laundering)' };
    }

    // 2. 检测：分拆洗钱 (Smurfing/Layering)
    if (this.detectHighVelocity(tx.to)) {
      logger.warn(`[FraudDetection] WARNING: High velocity layering detected for node ${tx.to}`);
      return { isSuspicious: true, reason: 'High velocity incoming transactions (Potential Smurfing)' };
    }

    return { isSuspicious: false };
  }

  /**
   * 简单的环形路径检测 (DFS)
   */
  private static detectCycle(start: string, current: string, depth: number = 0): boolean {
    if (depth > 5) return false; // 限制深度
    if (current === start) return true;

    const neighbors = this.edges.filter(e => e.from === current).map(e => e.to);
    for (const next of neighbors) {
      if (this.detectCycle(start, next, depth + 1)) return true;
    }
    return false;
  }

  /**
   * 高频交易检测：如果在 1 小时内有超过 10 笔来自不同来源的小额交易
   */
  private static detectHighVelocity(nodeId: string): boolean {
    const oneHourAgo = new Date(Date.now() - 3600000);
    const recentTx = this.edges.filter(e => e.to === nodeId && e.timestamp > oneHourAgo);
    
    // 逻辑：如果交易笔数 > 10 且平均金额较小，则判定为疑似分拆洗钱
    return recentTx.length > 10;
  }

  /**
   * 更新节点风险分
   */
  static async updateNodeRisk(nodeId: string, score: number) {
    const node = this.nodes.get(nodeId) || { id: nodeId, type: 'WALLET', riskScore: 0 };
    node.riskScore = score;
    this.nodes.set(nodeId, node);
  }
}
