// Wallet Risk Service
import { Prisma } from '@prisma/client';
// Real-time risk scoring

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';


export interface RiskScoreRequest {
  walletId: string;
}

export interface RiskScoreResult {
  scoreId: string;
  riskScore: string;
  riskFactors: Record<string, unknown>;
}

export class WalletRiskService {
  /**
   * Calculate wallet risk score
   */
  async calculateRiskScore(
    request: RiskScoreRequest
  ): Promise<RiskScoreResult> {
    const wallet = await prisma.quantum_wallets.findUnique({
      where: { walletId: request.walletId },
      include: {
        wallet_attestation_objects: {
          orderBy: { attestedAt: 'desc' },
          take: 1,
        },
        wallet_risk_scores: {
          orderBy: { calculatedAt: 'desc' },
          take: 5,
        },
      },
    });

    if (!wallet) {
      throw new Error(`Wallet not found: ${request.walletId}`);
    }

    const riskFactors: Record<string, unknown> = {};
    let riskScore = 0;

    // Factor 1: Wallet type (retail = lower risk, institutional = higher risk)
    const typeRisk = wallet.walletType === 'retail' ? 10 : wallet.walletType === 'wholesale' ? 30 : 50;
    riskFactors.walletType = typeRisk;
    riskScore += typeRisk;

    // Factor 2: Attestation status
    const latestAttestation = wallet.wallet_attestation_objects[0];
    if (!latestAttestation || latestAttestation.status !== 'valid') {
      riskFactors.attestationStatus = 30;
      riskScore += 30;
    } else {
      riskFactors.attestationStatus = 0;
    }

    // Factor 3: Balance (higher balance = higher risk)
    const balanceRisk = wallet.balance.greaterThan(new Decimal(1000000))
      ? 20
      : wallet.balance.greaterThan(new Decimal(100000))
      ? 10
      : 0;
    riskFactors.balance = balanceRisk;
    riskScore += balanceRisk;

    // Factor 4: Recent risk history
    if (wallet.wallet_risk_scores.length > 0) {
      const avgRecentScore = wallet.wallet_risk_scores.reduce(
        (sum, rs) => sum.plus(rs.riskScore),
        new Decimal(0)
      ).div(wallet.wallet_risk_scores.length);

      const historyRisk = avgRecentScore.greaterThan(new Decimal(70)) ? 20 : 0;
      riskFactors.history = historyRisk;
      riskScore += historyRisk;
    }

    // Normalize to 0-100 scale
    riskScore = Math.min(100, Math.max(0, riskScore));

    // Create risk score record
    const scoreId = `RISK-${uuidv4()}`;
    const score = await prisma.wallet_risk_scores.create({
      data: {
        id: uuidv4(),
        scoreId,
        walletId: request.walletId,
        riskScore: new Decimal(riskScore),
        riskFactors: riskFactors as Prisma.InputJsonValue,
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    return {
      scoreId: score.scoreId,
      riskScore: score.riskScore.toString(),
      riskFactors: score.riskFactors as Record<string, unknown>,
    };
  }

  /**
   * Get latest risk score
   */
  async getLatestRiskScore(walletId: string): Promise<any | null> {
    const score = await prisma.wallet_risk_scores.findFirst({
      where: { walletId },
      orderBy: { calculatedAt: 'desc' },
    });

    return score;
  }

  /**
   * Get risk score history
   */
  async getRiskScoreHistory(walletId: string, limit: number = 10): Promise<any[]> {
    const scores = await prisma.wallet_risk_scores.findMany({
      where: { walletId },
      orderBy: { calculatedAt: 'desc' },
      take: limit,
    });

    return scores;
  }
}

export const walletRiskService = new WalletRiskService();

