// DBIS Admin Console - Global Overview Dashboard Service
// Network health, settlement throughput, GRU & liquidity, risk flags, SCB status

import prisma from '@/shared/database/prisma';
import { logger } from '@/infrastructure/monitoring/logger';
import { dashboardService } from '@/core/compliance/regtech/dashboard.service';
import Decimal from 'decimal.js';

export interface NetworkHealthStatus {
  subsystem: string;
  status: 'healthy' | 'degraded' | 'down';
  lastHeartbeat?: Date;
  latency?: number;
  errorRate?: number;
}

export interface SettlementThroughput {
  txPerSecond: number;
  dailyVolume: number;
  byAssetType: {
    fiat: number;
    cbdc: number;
    gru: number;
    ssu: number;
    commodities: number;
  };
  heatmap: Array<{
    sourceSCB: string;
    destinationSCB: string;
    volume: number;
  }>;
}

export interface GRULiquidityMetrics {
  currentPrice: number;
  volatility: number;
  inCirculation: {
    m00: number;
    m0: number;
    m1: number;
    sr1: number;
    sr2: number;
    sr3: number;
  };
}

export interface RiskFlags {
  high: number;
  medium: number;
  low: number;
  alerts: Array<{
    id: string;
    type: string;
    severity: string;
    description: string;
    timestamp: Date;
  }>;
}

export interface SCBStatus {
  scbId: string;
  name: string;
  country: string;
  bic?: string;
  status: string;
  connectivity: 'connected' | 'degraded' | 'disconnected';
  latency?: number;
  errorRate?: number;
  openIncidents: number;
}

export interface GlobalOverviewDashboard {
  networkHealth: NetworkHealthStatus[];
  settlementThroughput: SettlementThroughput;
  gruLiquidity: GRULiquidityMetrics;
  riskFlags: RiskFlags;
  scbStatus: SCBStatus[];
}

export class GlobalOverviewService {
  /**
   * Get global overview dashboard
   */
  async getGlobalOverview(): Promise<GlobalOverviewDashboard> {
    const [networkHealth, settlementThroughput, gruLiquidity, riskFlags, scbStatus] =
      await Promise.all([
        this.getNetworkHealth(),
        this.getSettlementThroughput(),
        this.getGRULiquidity(),
        this.getRiskFlags(),
        this.getSCBStatus(),
      ]);

    return {
      networkHealth,
      settlementThroughput,
      gruLiquidity,
      riskFlags,
      scbStatus,
    };
  }

  /**
   * Get network health status for all subsystems
   */
  async getNetworkHealth(): Promise<NetworkHealthStatus[]> {
    const subsystems: NetworkHealthStatus[] = [];

    // GAS (Global Atomic Settlement)
    try {
      const gasSettlements = await prisma.atomic_settlements.findMany({
        where: {
          createdAt: {
            gte: new Date(Date.now() - 5 * 60 * 1000), // Last 5 minutes
          },
        },
        take: 100,
      });

      const successRate =
        gasSettlements.length > 0
          ? gasSettlements.filter((s: any) => s.status === 'settled').length /
            gasSettlements.length
          : 1.0;

      subsystems.push({
        subsystem: 'GAS',
        status: successRate > 0.95 ? 'healthy' : successRate > 0.8 ? 'degraded' : 'down',
        errorRate: 1 - successRate,
      });
    } catch (error) {
      logger.error('Error getting GAS health', { error });
      subsystems.push({ subsystem: 'GAS', status: 'down' });
    }

    // QPS (Quantum Payment System) - placeholder
    subsystems.push({
      subsystem: 'QPS',
      status: 'healthy',
    });

    // Ω-Layer (Omega Layer) - placeholder
    subsystems.push({
      subsystem: 'Ω-Layer',
      status: 'healthy',
    });

    // GPN (Global Payment Network) - placeholder
    subsystems.push({
      subsystem: 'GPN',
      status: 'healthy',
    });

    // GRU Engine - placeholder
    subsystems.push({
      subsystem: 'GRU Engine',
      status: 'healthy',
    });

    // Metaverse MEN - placeholder
    subsystems.push({
      subsystem: 'Metaverse MEN',
      status: 'healthy',
    });

    // 6G Edge Grid - placeholder
    subsystems.push({
      subsystem: '6G Edge Grid',
      status: 'healthy',
    });

    return subsystems;
  }

  /**
   * Get settlement throughput metrics
   */
  async getSettlementThroughput(): Promise<SettlementThroughput> {
    const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
    const oneMinuteAgo = new Date(Date.now() - 60 * 1000);

    // Get all settlements in last 24 hours
      const settlements = await prisma.atomic_settlements.findMany({
      where: {
        createdAt: {
          gte: oneDayAgo,
        },
      },
    });

    // Get settlements in last minute for tx/sec
    const recentSettlements = settlements.filter(
      (s: any) => s.createdAt >= oneMinuteAgo
    );

    const txPerSecond = recentSettlements.length / 60;

    // Calculate daily volume
    const dailyVolume = settlements
        .filter((s: any) => s.status === 'settled')
        .reduce((sum: Decimal, s: { amount?: unknown }) => sum.plus(Number(s.amount ?? 0)), new Decimal(0))
      .toNumber();

    // Group by asset type
    const byAssetType = {
      fiat: 0,
      cbdc: 0,
      gru: 0,
      ssu: 0,
      commodities: 0,
    };

    settlements.forEach((s: any) => {
      if (s.assetType === 'currency') byAssetType.fiat += parseFloat(s.amount.toString());
      else if (s.assetType === 'cbdc') byAssetType.cbdc += parseFloat(s.amount.toString());
      else if (s.assetType === 'commodity') byAssetType.commodities += parseFloat(s.amount.toString());
      // GRU and SSU would need additional queries
    });

    // Heatmap: top corridors by volume
    const corridorMap = new Map<string, number>();
    settlements.forEach((s: any) => {
      if (s.status === 'settled') {
        const key = `${s.sourceBankId}-${s.destinationBankId}`;
        const current = corridorMap.get(key) || 0;
        corridorMap.set(key, current + parseFloat(s.amount.toString()));
      }
    });

    const heatmap = Array.from(corridorMap.entries())
      .map(([key, volume]) => {
        const [source, dest] = key.split('-');
        return { sourceSCB: source, destinationSCB: dest, volume };
      })
      .sort((a, b) => b.volume - a.volume)
      .slice(0, 20); // Top 20

    return {
      txPerSecond,
      dailyVolume,
      byAssetType,
      heatmap,
    };
  }

  /**
   * Get GRU & liquidity metrics
   */
  async getGRULiquidity(): Promise<GRULiquidityMetrics> {
    // Get GRU units
    const gruUnits = await prisma.gru_units.findMany({
      where: { status: 'active' },
    });

    // Calculate in circulation by class
    const inCirculation = {
      m00: 0,
      m0: 0,
      m1: 0,
      sr1: 0,
      sr2: 0,
      sr3: 0,
    };

    // Get GRU indexes for price
    const indexes = await prisma.gru_indexes.findMany({
      where: { status: 'active' },
      include: { gru_index_price_history: { orderBy: { timestamp: 'desc' }, take: 2 } },
    });

    let currentPrice = 1.0; // Default
    let volatility = 0.0;

    if (indexes.length > 0 && (indexes[0] as { gru_index_price_history?: Array<{ indexValue?: unknown }> }).gru_index_price_history?.length >= 2) {
      const priceHistory = (indexes[0] as { gru_index_price_history: Array<{ indexValue?: unknown }> }).gru_index_price_history;
      const [latest, previous] = priceHistory;
      currentPrice = parseFloat(String(latest?.indexValue ?? 1));
      const prevPrice = previous ? parseFloat(String(previous.indexValue ?? 1)) : currentPrice;
      volatility = prevPrice > 0 ? Math.abs((currentPrice - prevPrice) / prevPrice) : 0;
    }

    return {
      currentPrice,
      volatility,
      inCirculation,
    };
  }

  /**
   * Get risk flags and alerts
   */
  async getRiskFlags(): Promise<RiskFlags> {
    const dashboard = await dashboardService.getIncidentAlertsDashboard();

    const alerts = dashboard.incidentAlerts || [];
    const high = alerts.filter((a: any) => a.severity === 'critical' || a.severity === 'high').length;
    const medium = alerts.filter((a: any) => a.severity === 'medium').length;
    const low = alerts.filter((a: any) => a.severity === 'low').length;

    return {
      high,
      medium,
      low,
      alerts: alerts.slice(0, 10).map((a: any, idx: number) => ({
        id: a.id || `alert-${idx}`,
        type: a.type || 'unknown',
        severity: a.severity || 'low',
        description: a.description || '',
        timestamp: a.timestamp || new Date(),
      })),
    };
  }

  /**
   * Get SCB status table
   */
  async getSCBStatus(): Promise<SCBStatus[]> {
    const scbs = await prisma.sovereign_banks.findMany({
      where: { status: { in: ['active', 'suspended'] } },
    });

    const scbStatus: SCBStatus[] = [];

    for (const scb of scbs) {
      // Get recent settlements to determine connectivity
      const recentSettlements = await prisma.atomic_settlements.findMany({
        where: {
          OR: [{ sourceBankId: scb.id }, { destinationBankId: scb.id }],
          createdAt: {
            gte: new Date(Date.now() - 5 * 60 * 1000), // Last 5 minutes
          },
        },
        take: 10,
      });

      const connectivity =
        recentSettlements.length > 0 ? 'connected' : 'degraded';

      // Get open incidents (SRI enforcements)
      const openIncidents = await prisma.sri_enforcements.count({
        where: {
          sovereignBankId: scb.id,
          status: 'active',
        },
      });

      scbStatus.push({
        scbId: scb.id,
        name: scb.name,
        country: scb.sovereignCode,
        bic: scb.bic || undefined,
        status: scb.status,
        connectivity,
        openIncidents,
      });
    }

    return scbStatus;
  }
}

export const globalOverviewService = new GlobalOverviewService();

