// Sovereign Identity Fabric (SIF) - Root Sovereign Identity Management

import { hsmService } from '@/integration/hsm/hsm.service';
import { IdentityType, SovereignIdentity } from '@/shared/types';
import prisma from '@/shared/database/prisma';

export interface RootSovereignIdentity {
  sovereignBankId: string;
  rootSovereignKey: string; // HSM key ID
  identities: Map<IdentityType, string>; // Identity type -> HSM key ID
}

/**
 * Sovereign Identity Fabric Service
 * Manages tiered identities for sovereign banks
 */
export class SovereignIdentityFabricService {
  private rootIdentities: Map<string, RootSovereignIdentity> = new Map();

  /**
   * Create Root Sovereign Identity (RSK) for a sovereign bank
   */
  async createRootSovereignIdentity(
    sovereignBankId: string,
    sovereignCode: string
  ): Promise<RootSovereignIdentity> {
    // Generate Root Sovereign Key in HSM
    const rootKey = await hsmService.generateKeyPair('ECC-521', `RSK-${sovereignCode}`);

    const rootIdentity: RootSovereignIdentity = {
      sovereignBankId,
      rootSovereignKey: rootKey.keyId,
      identities: new Map(),
    };

    // Create Master Identity
    const masterKey = await hsmService.generateKeyPair('ECC-521', `MASTER-${sovereignCode}`);
    rootIdentity.identities.set(IdentityType.MASTER, masterKey.keyId);

    // Store in database
    await prisma.sovereignIdentity.create({
      data: {
        sovereignBankId,
        identityType: IdentityType.MASTER,
        identityKey: masterKey.publicKey,
        hsmKeyId: masterKey.keyId,
        status: 'active',
      },
    });

    // Update sovereign bank record
    await prisma.sovereignBank.update({
      where: { id: sovereignBankId },
      data: {
        rootSovereignKey: rootKey.keyId,
        hsmIdentity: rootKey.keyId,
      },
    });

    this.rootIdentities.set(sovereignBankId, rootIdentity);
    return rootIdentity;
  }

  /**
   * Create tiered identity (Treasury, CBDC, Settlement, API)
   */
  async createTieredIdentity(
    sovereignBankId: string,
    identityType: IdentityType,
    sovereignCode: string
  ): Promise<string> {
    const rootIdentity = this.rootIdentities.get(sovereignBankId);
    if (!rootIdentity) {
      throw new Error(`Root identity not found for sovereign bank: ${sovereignBankId}`);
    }

    // Generate identity key in HSM
    const identityKey = await hsmService.generateKeyPair(
      'ECC-521',
      `${identityType}-${sovereignCode}`
    );

    rootIdentity.identities.set(identityType, identityKey.keyId);

    // Store in database
    await prisma.sovereignIdentity.create({
      data: {
        sovereignBankId,
        identityType,
        identityKey: identityKey.publicKey,
        hsmKeyId: identityKey.keyId,
        status: 'active',
      },
    });

    return identityKey.keyId;
  }

  /**
   * Get identity for a sovereign bank and identity type
   */
  async getIdentity(
    sovereignBankId: string,
    identityType: string
  ): Promise<{ hsmKeyId: string; identityKey: string } | null> {
    const identity = await prisma.sovereignIdentity.findFirst({
      where: {
        sovereignBankId,
        identityType,
        status: 'active',
      },
    });

    if (!identity || !identity.hsmKeyId) {
      return null;
    }

    return {
      hsmKeyId: identity.hsmKeyId,
      identityKey: identity.identityKey,
    };
  }

  /**
   * Get identity key ID for a sovereign bank and identity type
   */
  async getIdentityKeyId(
    sovereignBankId: string,
    identityType: IdentityType
  ): Promise<string | null> {
    const identity = await this.getIdentity(sovereignBankId, identityType);
    return identity?.hsmKeyId || null;
  }

  /**
   * Sign data using sovereign identity
   */
  async signWithSovereignIdentity(
    data: string,
    sovereignBankId: string,
    identityType: IdentityType
  ): Promise<string> {
    const keyId = await this.getIdentityKeyId(sovereignBankId, identityType);
    if (!keyId) {
      throw new Error(
        `Identity not found: ${sovereignBankId} - ${identityType}`
      );
    }

    const signature = await hsmService.sign(data, keyId);
    return signature.signature;
  }

  /**
   * Verify signature using sovereign identity
   */
  async verifySovereignSignature(
    data: string,
    signature: string,
    sovereignBankId: string,
    identityType: IdentityType
  ): Promise<boolean> {
    const keyId = await this.getIdentityKeyId(sovereignBankId, identityType);
    if (!keyId) {
      return false;
    }

    return await hsmService.verify(data, signature, keyId);
  }

  /**
   * Rotate sovereign identity key
   */
  async rotateIdentity(
    sovereignBankId: string,
    identityType: IdentityType,
    sovereignCode: string
  ): Promise<string> {
    const oldKeyId = await this.getIdentityKeyId(sovereignBankId, identityType);
    
    if (oldKeyId) {
      await hsmService.destroyKey(oldKeyId);
    }

    return await this.createTieredIdentity(sovereignBankId, identityType, sovereignCode);
  }

  /**
   * Get all identities for a sovereign bank
   */
  async getSovereignIdentities(sovereignBankId: string): Promise<SovereignIdentity[]> {
    const identities = await prisma.sovereignIdentity.findMany({
      where: {
        sovereignBankId,
        status: 'active',
      },
    });
    return identities.map(identity => ({
      ...identity,
      identityType: identity.identityType as IdentityType,
      hsmKeyId: identity.hsmKeyId ?? undefined,
      certificate: identity.certificate ?? undefined,
    }));
  }
}

export const sovereignIdentityFabric = new SovereignIdentityFabricService();

