// AML/CTF System - Transaction Monitoring, Sanctions Screening

import {
  ComplianceRecord,
  ComplianceRecordType,
  ComplianceStatus,
} from '@/shared/types';
import { COMPLIANCE_THRESHOLDS } from '@/shared/constants';
import { v4 as uuidv4 } from 'uuid';
import { supervisionEngineService } from './regtech/supervision-engine.service';
import { Prisma } from '@prisma/client';
import prisma from '@/shared/database/prisma';

export class AmlService {
  /**
   * Screen transaction for AML/CTF compliance
   */
  async screenTransaction(
    sovereignBankId: string,
    transactionId: string,
    entityName?: string,
    entityType?: string
  ): Promise<ComplianceRecord> {
    let riskScore = 0;
    const screeningResults: Record<string, unknown> = {};

    // Sanctions screening
    if (entityName) {
      const sanctionsMatch = await this.checkSanctionsList(entityName);
      if (sanctionsMatch) {
        riskScore += 100; // Critical match
        screeningResults.sanctionsMatch = true;
      }
    }

    // PEP screening
    if (entityName) {
      const pepMatch = await this.checkPepList(entityName);
      if (pepMatch) {
        riskScore += 50; // High risk
        screeningResults.pepMatch = true;
      }
    }

    // Pattern detection
    const patternRisk = await this.detectAnomalousPattern(transactionId);
    riskScore += patternRisk;
    screeningResults.patternRisk = patternRisk;

    // Use RegTech supervision engine for AML behavior monitoring
    const amlBehaviors = await supervisionEngineService.monitorAMLBehaviors(transactionId, sovereignBankId);
    if (amlBehaviors.length > 0) {
      const criticalBehaviors = amlBehaviors.filter((b) => b.severity === 'critical');
      riskScore += criticalBehaviors.length * 50;
      screeningResults.amlBehaviors = amlBehaviors;
    }

    // Determine status
    let status: ComplianceStatus = ComplianceStatus.CLEAR;
    if (riskScore >= COMPLIANCE_THRESHOLDS.AML_RISK_CRITICAL) {
      status = ComplianceStatus.BLOCKED;
    } else if (riskScore >= COMPLIANCE_THRESHOLDS.AML_RISK_HIGH) {
      status = ComplianceStatus.FLAGGED;
    }

    // Create compliance record
    const record = await prisma.compliance_records.create({
      data: {
        id: uuidv4(),
        sovereignBankId,
        transactionId,
        recordType: ComplianceRecordType.AML_CHECK,
        entityName,
        entityType,
        riskScore,
        status,
        screeningResult: screeningResults as Prisma.InputJsonValue,
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    return this.mapToComplianceRecord(record);
  }

  /**
   * Check sanctions list
   */
  private async checkSanctionsList(entityName: string): Promise<boolean> {
    // In production, this would check OFAC, EU, UN sanctions lists
    // For now, return mock result
    const sanctionsList = await prisma.sanctions_lists.findFirst({
      where: {
        entityName: {
          contains: entityName,
          mode: 'insensitive',
        },
        status: 'active',
      },
    });

    return !!sanctionsList;
  }

  /**
   * Check PEP (Politically Exposed Person) list
   */
  private async checkPepList(entityName: string): Promise<boolean> {
    // In production, this would check PEP databases
    // For now, return mock result
    return false;
  }

  /**
   * Detect anomalous patterns
   */
  private async detectAnomalousPattern(transactionId: string): Promise<number> {
    // In production, this would use ML models to detect patterns
    // For now, return mock risk score
    return 0;
  }

  /**
   * Map Prisma model to ComplianceRecord type
   */
  private mapToComplianceRecord(record: any): ComplianceRecord {
    return {
      id: record.id,
      sovereignBankId: record.sovereignBankId,
      transactionId: record.transactionId || undefined,
      recordType: record.recordType as ComplianceRecordType,
      entityName: record.entityName || undefined,
      entityType: record.entityType || undefined,
      riskScore: record.riskScore,
      status: record.status as ComplianceStatus,
      screeningResult: record.screeningResult as Record<string, unknown> | undefined,
    };
  }
}

export const amlService = new AmlService();

