// Regulatory Equivalence Protocol (REP) Service

import prisma from '@/shared/database/prisma';
import { RegulatoryEquivalenceScore } from './types';
import { logger } from '@/infrastructure/monitoring/logger';
import { v4 as uuidv4 } from 'uuid';


export class RegulatoryEquivalenceService {
  /**
   * Calculate REP score for a sovereign
   * REP_SCORE = (compliance + transparency + AML_strength + CBDC_maturity) / 4
   */
  async calculateREPScore(sovereignBankId: string): Promise<RegulatoryEquivalenceScore> {
    // Get compliance score
    const compliance = await this.calculateComplianceScore(sovereignBankId);

    // Get transparency score
    const transparency = await this.calculateTransparencyScore(sovereignBankId);

    // Get AML strength score
    const amlStrength = await this.calculateAMLStrengthScore(sovereignBankId);

    // Get CBDC maturity score
    const cbdcMaturity = await this.calculateCBDCMaturityScore(sovereignBankId);

    // Calculate REP score
    const repScore = (compliance + transparency + amlStrength + cbdcMaturity) / 4;

    // Determine equivalence (>= 95%)
    const equivalent = repScore >= 95;

    const score: RegulatoryEquivalenceScore = {
      sovereignBankId,
      compliance,
      transparency,
      amlStrength,
      cbdcMaturity,
      repScore,
      equivalent,
      calculatedAt: new Date(),
    };

    // Store score
    await prisma.regulatory_equivalence_scores.create({
      data: {
        id: uuidv4(),
        scoreId: `REP-${sovereignBankId}-${Date.now()}`,
        sovereignBankId,
        compliance,
        transparency,
        amlStrength,
        cbdcMaturity,
        repScore,
        equivalent,
      },
    });

    logger.info(`Calculated REP score for ${sovereignBankId}`, {
      repScore,
      equivalent,
    });

    return score;
  }

  /**
   * Calculate compliance score (0-100)
   */
  private async calculateComplianceScore(sovereignBankId: string): Promise<number> {
    // Get harmonization compliance records
    const complianceRecords = await prisma.harmonization_compliance.findMany({
      where: { sovereignBankId },
    });

    if (complianceRecords.length === 0) {
      return 0;
    }

    // Calculate average compliance score
    const totalScore = complianceRecords.reduce((sum: number, record: { complianceScore?: unknown }) => sum + Number(record.complianceScore), 0);
    return totalScore / complianceRecords.length;
  }

  /**
   * Calculate transparency score (0-100)
   */
  private async calculateTransparencyScore(sovereignBankId: string): Promise<number> {
    // Factors: reporting frequency, data quality, audit compliance
    // For now, use a simplified calculation
    const sovereignBank = await prisma.sovereign_banks.findUnique({
      where: { id: sovereignBankId },
    });

    if (!sovereignBank) {
      return 0;
    }

    // Base score from status
    let score = sovereignBank.status === 'active' ? 50 : 0;

    // Add points for having BIC and LEI
    if (sovereignBank.bic) score += 25;
    if (sovereignBank.lei) score += 25;

    return Math.min(100, score);
  }

  /**
   * Calculate AML strength score (0-100)
   */
  private async calculateAMLStrengthScore(sovereignBankId: string): Promise<number> {
    // Get recent compliance records
    const recentRecords = await prisma.compliance_records.findMany({
      where: {
        sovereignBankId,
        createdAt: {
          gte: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000), // Last 90 days
        },
      },
    });

    if (recentRecords.length === 0) {
      return 50; // Neutral score if no records
    }

    // Calculate based on risk scores (lower risk = higher strength)
    const avgRiskScore = recentRecords.reduce((sum: number, r: { riskScore?: number }) => sum + (r.riskScore ?? 0), 0) / recentRecords.length;
    const strengthScore = Math.max(0, 100 - avgRiskScore);

    return strengthScore;
  }

  /**
   * Calculate CBDC maturity score (0-100)
   */
  private async calculateCBDCMaturityScore(sovereignBankId: string): Promise<number> {
    // Check CBDC issuance activity
    const cbdcIssuances = await prisma.cbdc_issuance.findMany({
      where: { sovereignBankId },
    });

    if (cbdcIssuances.length === 0) {
      return 0; // No CBDC activity
    }

    // Base score from having CBDC
    let score = 50;

    // Add points for recent activity
    const recentIssuances = cbdcIssuances.filter(
      (i) => i.timestampUtc > new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
    );
    if (recentIssuances.length > 0) {
      score += 30;
    }

    // Add points for volume
    const totalVolume = cbdcIssuances.reduce((sum: number, i: { netChange?: unknown }) => sum + Number(i.netChange), 0);
    if (totalVolume > 1000000) {
      score += 20;
    }

    return Math.min(100, score);
  }

  /**
   * Get REP score for sovereign
   */
  async getREPScore(sovereignBankId: string): Promise<RegulatoryEquivalenceScore | null> {
    const score = await prisma.regulatory_equivalence_scores.findFirst({
      where: { sovereignBankId },
      orderBy: { calculatedAt: 'desc' },
    });

    if (!score) {
      return null;
    }

    return {
      sovereignBankId: score.sovereignBankId,
      compliance: Number(score.compliance),
      transparency: Number(score.transparency),
      amlStrength: Number(score.amlStrength),
      cbdcMaturity: Number(score.cbdcMaturity),
      repScore: Number(score.repScore),
      equivalent: score.equivalent,
      calculatedAt: score.calculatedAt,
    };
  }

  /**
   * Grant fast-track privileges for equivalent sovereigns
   */
  async grantFastTrackPrivileges(sovereignBankId: string): Promise<void> {
    const repScore = await this.getREPScore(sovereignBankId);

    if (!repScore || !repScore.equivalent) {
      throw new Error(`Sovereign ${sovereignBankId} is not regulatory equivalent`);
    }

    // Grant settlement privilege
    await prisma.fast_track_privileges.create({
      data: {
        id: uuidv4(),
        privilegeId: `FTP-SETTLEMENT-${sovereignBankId}-${Date.now()}`,
        sovereignBankId,
        privilegeType: 'SETTLEMENT',
        status: 'ACTIVE',
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    // Grant liquidity privilege
    await prisma.fast_track_privileges.create({
      data: {
        id: uuidv4(),
        privilegeId: `FTP-LIQUIDITY-${sovereignBankId}-${Date.now()}`,
        sovereignBankId,
        privilegeType: 'LIQUIDITY',
        status: 'ACTIVE',
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    // Grant oversight privilege (reduced oversight frequency)
    await prisma.fast_track_privileges.create({
      data: {
        id: uuidv4(),
        privilegeId: `FTP-OVERSIGHT-${sovereignBankId}-${Date.now()}`,
        sovereignBankId,
        privilegeType: 'OVERSIGHT',
        status: 'ACTIVE',
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    logger.info(`Granted fast-track privileges to ${sovereignBankId}`);
  }

  /**
   * Check if sovereign has fast-track privileges
   */
  async hasFastTrackPrivilege(
    sovereignBankId: string,
    privilegeType: 'SETTLEMENT' | 'LIQUIDITY' | 'OVERSIGHT'
  ): Promise<boolean> {
    const privilege = await prisma.fast_track_privileges.findFirst({
      where: {
        sovereignBankId,
        privilegeType,
        status: 'ACTIVE',
      },
    });

    return !!privilege;
  }
}

export const regulatoryEquivalenceService = new RegulatoryEquivalenceService();

