// PSG Architecture Service
// Geo-redundant node management (3+ per SCB), PQ-encrypted replication links

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';


export interface GeoRedundantNodeConfig {
  sovereignBankId: string;
  region: string;
  replicationLinks?: Record<string, unknown>[];
}

export class PsgArchitectureService {
  /**
   * Create geo-redundant sovereign node
   */
  async createGeoRedundantNode(config: GeoRedundantNodeConfig) {
    const nodeId = `PSG-NODE-${config.sovereignBankId}-${uuidv4()}`;

    return await prisma.psgSovereignNode.create({
      data: {
        nodeId,
        sovereignBankId: config.sovereignBankId,
        region: config.region,
        nodeType: 'geo_redundant',
        replicationLinks: config.replicationLinks || [],
        status: 'active',
      },
    });
  }

  /**
   * Ensure minimum 3 geo-redundant nodes per SCB
   */
  async ensureMinimumRedundancy(sovereignBankId: string, regions: string[]) {
    const existingNodes = await prisma.psgSovereignNode.findMany({
      where: {
        sovereignBankId,
        status: 'active',
      },
    });

    if (existingNodes.length >= 3) {
      return existingNodes;
    }

    const nodesToCreate = 3 - existingNodes.length;
    const newNodes = [];

    for (let i = 0; i < nodesToCreate && i < regions.length; i++) {
      const region = regions[i] || `region-${i + 1}`;
      const node = await this.createGeoRedundantNode({
        sovereignBankId,
        region,
        replicationLinks: [],
      });
      newNodes.push(node);
    }

    return [...existingNodes, ...newNodes];
  }

  /**
   * Add PQ-encrypted replication link
   */
  async addReplicationLink(
    nodeId: string,
    targetNodeId: string,
    encryptionConfig: Record<string, unknown>
  ) {
    const node = await prisma.psgSovereignNode.findUnique({
      where: { nodeId },
    });

    if (!node) {
      throw new Error(`Node not found: ${nodeId}`);
    }

    const replicationLinks = (node.replicationLinks as Record<string, unknown>[]) || [];
    replicationLinks.push({
      targetNodeId,
      encryptionConfig,
      createdAt: new Date(),
    });

    return await prisma.psgSovereignNode.update({
      where: { nodeId },
      data: {
        replicationLinks,
      },
    });
  }

  /**
   * Get nodes for sovereign bank
   */
  async getNodesForBank(sovereignBankId: string) {
    return await prisma.psgSovereignNode.findMany({
      where: {
        sovereignBankId,
        status: 'active',
      },
    });
  }

  /**
   * Get node by ID
   */
  async getNode(nodeId: string) {
    return await prisma.psgSovereignNode.findUnique({
      where: { nodeId },
    });
  }

  /**
   * Update node sync status
   */
  async updateNodeSync(nodeId: string) {
    return await prisma.psgSovereignNode.update({
      where: { nodeId },
      data: {
        lastSyncAt: new Date(),
      },
    });
  }
}

export const psgArchitectureService = new PsgArchitectureService();

