// Suspicious Activity Score (SAS) Calculator Service

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { SuspiciousActivityScore, RiskTier } from './types';
import { sanctionsSyncService } from './sanctions-sync.service';
import { pepGraphService } from './pep-graph.service';
import { logger } from '@/infrastructure/monitoring/logger';


export class SASCalculatorService {
  /**
   * Calculate Suspicious Activity Score for transaction
   */
  async calculateSAS(transactionId: string, entityId: string): Promise<SuspiciousActivityScore> {
    const factors = {
      sanctionsMatch: 0,
      pepMatch: 0,
      patternRisk: 0,
      velocityAnomaly: 0,
      geographicRisk: 0,
    };

    // Check sanctions match
    const entity = await this.getEntityById(entityId);
    if (entity) {
      const sanctionsMatches = await sanctionsSyncService.searchSanctions(entity.name || entityId);
      if (sanctionsMatches.length > 0) {
        factors.sanctionsMatch = Math.min(100, sanctionsMatches[0].matchScore * 100);
      }
    }

    // Check PEP match
    const isPEP = await pepGraphService.isPEP(entityId);
    if (isPEP) {
      const pepNode = await pepGraphService.getPEPNode(entityId);
      if (pepNode) {
        factors.pepMatch = pepNode.riskLevel === 'HIGH' ? 100 : pepNode.riskLevel === 'MEDIUM' ? 50 : 25;
      }
    }

    // Check pattern risk (from transaction history)
    factors.patternRisk = await this.calculatePatternRisk(transactionId, entityId);

    // Check velocity anomaly
    factors.velocityAnomaly = await this.calculateVelocityAnomaly(entityId);

    // Check geographic risk
    factors.geographicRisk = await this.calculateGeographicRisk(transactionId);

    // Calculate total score
    const score = Math.min(100, (
      factors.sanctionsMatch * 0.4 +
      factors.pepMatch * 0.3 +
      factors.patternRisk * 0.15 +
      factors.velocityAnomaly * 0.1 +
      factors.geographicRisk * 0.05
    ));

    // Determine risk tier
    const riskTier = this.determineRiskTier(score);

    const sas: SuspiciousActivityScore = {
      transactionId,
      entityId,
      score,
      factors,
      riskTier,
      calculatedAt: new Date(),
    };

    // Store SAS
    await prisma.suspicious_activity_scores.create({
      data: {
        id: uuidv4(),
        sasId: `SAS-${transactionId}-${Date.now()}`,
        transactionId,
        entityId,
        score,
        factors,
        riskTier,
      },
    });

    logger.info(`Calculated SAS for transaction ${transactionId}`, {
      score,
      riskTier,
    });

    return sas;
  }

  /**
   * Calculate pattern risk
   */
  private async calculatePatternRisk(transactionId: string, entityId: string): Promise<number> {
    // Get recent transactions
    const recentTransactions = 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() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
        },
      },
      take: 100,
    });

    // Simple pattern detection: high frequency = higher risk
    if (recentTransactions.length > 50) {
      return 50;
    } else if (recentTransactions.length > 20) {
      return 25;
    }

    return 0;
  }

  /**
   * Calculate velocity anomaly
   */
  private async calculateVelocityAnomaly(entityId: string): Promise<number> {
    // Get transaction velocity
    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() - 24 * 60 * 60 * 1000), // Last 24 hours
        },
      },
    });

    // High velocity = anomaly
    if (transactions.length > 100) {
      return 75;
    } else if (transactions.length > 50) {
      return 50;
    } else if (transactions.length > 20) {
      return 25;
    }

    return 0;
  }

  /**
   * Calculate geographic risk
   */
  private async calculateGeographicRisk(transactionId: string): Promise<number> {
    // Simplified: check if transaction involves high-risk countries
    // In production, this would use actual geographic risk data
    return 0;
  }

  /**
   * Determine risk tier from score
   */
  private determineRiskTier(score: number): RiskTier {
    if (score >= 75) {
      return RiskTier.TIER_4;
    } else if (score >= 50) {
      return RiskTier.TIER_3;
    } else if (score >= 25) {
      return RiskTier.TIER_2;
    } else {
      return RiskTier.TIER_1;
    }
  }

  /**
   * Get entity by ID
   */
  private async getEntityById(entityId: string) {
    // Try to get from sovereign bank
    const bank = await prisma.sovereign_banks.findUnique({
      where: { id: entityId },
    });

    if (bank) {
      return { name: bank.name, type: 'BANK' };
    }

    return null;
  }

  /**
   * Get SAS for transaction
   */
  async getSAS(transactionId: string): Promise<SuspiciousActivityScore | null> {
    const sas = await prisma.suspicious_activity_scores.findFirst({
      where: { transactionId },
      orderBy: { calculatedAt: 'desc' },
    });

    if (!sas) {
      return null;
    }

    return {
      transactionId: sas.transactionId,
      entityId: sas.entityId,
      score: Number(sas.score),
      factors: sas.factors as any,
      riskTier: sas.riskTier as RiskTier,
      calculatedAt: sas.calculatedAt,
    };
  }
}

export const sasCalculatorService = new SASCalculatorService();

