/**
 * Financial role credential system
 * Comptroller General, Monetary Compliance Officer, Custodian of Digital Assets, Financial Auditor credentials
 */

import { createVerifiableCredential } from '@the-order/database';
import { KMSClient } from '@the-order/crypto';
import { getEnv } from '@the-order/shared';
import { randomUUID } from 'crypto';

export type FinancialRole =
  | 'ComptrollerGeneral'
  | 'MonetaryComplianceOfficer'
  | 'CustodianOfDigitalAssets'
  | 'FinancialAuditor'
  | 'Treasurer'
  | 'ChiefFinancialOfficer';

export interface FinancialCredentialData {
  role: FinancialRole;
  appointmentDate: Date;
  appointmentAuthority: string;
  jurisdiction?: string;
  termLength?: number; // in years
  expirationDate?: Date;
  additionalClaims?: Record<string, unknown>;
}

/**
 * Financial credential type definitions
 */
export const FINANCIAL_CREDENTIAL_TYPES: Record<FinancialRole, string[]> = {
  ComptrollerGeneral: ['VerifiableCredential', 'FinancialCredential', 'ComptrollerGeneralCredential'],
  MonetaryComplianceOfficer: [
    'VerifiableCredential',
    'FinancialCredential',
    'MonetaryComplianceOfficerCredential',
  ],
  CustodianOfDigitalAssets: [
    'VerifiableCredential',
    'FinancialCredential',
    'CustodianOfDigitalAssetsCredential',
  ],
  FinancialAuditor: ['VerifiableCredential', 'FinancialCredential', 'FinancialAuditorCredential'],
  Treasurer: ['VerifiableCredential', 'FinancialCredential', 'TreasurerCredential'],
  ChiefFinancialOfficer: ['VerifiableCredential', 'FinancialCredential', 'ChiefFinancialOfficerCredential'],
};

/**
 * Issue financial role credential
 */
export async function issueFinancialCredential(
  subjectDid: string,
  credentialData: FinancialCredentialData,
  kmsClient: KMSClient
): Promise<string> {
  const env = getEnv();
  const issuerDid = env.VC_ISSUER_DID || (env.VC_ISSUER_DOMAIN ? `did:web:${env.VC_ISSUER_DOMAIN}` : undefined);

  if (!issuerDid) {
    throw new Error('VC_ISSUER_DID or VC_ISSUER_DOMAIN must be configured');
  }

  const credentialId = randomUUID();
  const issuanceDate = new Date();
  const expirationDate =
    credentialData.expirationDate ||
    (credentialData.termLength
      ? new Date(issuanceDate.getTime() + credentialData.termLength * 365 * 24 * 60 * 60 * 1000)
      : undefined);

  const credentialType = FINANCIAL_CREDENTIAL_TYPES[credentialData.role];

  const credentialSubject = {
    role: credentialData.role,
    appointmentDate: credentialData.appointmentDate.toISOString(),
    appointmentAuthority: credentialData.appointmentAuthority,
    jurisdiction: credentialData.jurisdiction,
    termLength: credentialData.termLength,
    ...credentialData.additionalClaims,
  };

  const credentialDataObj = {
    id: credentialId,
    type: credentialType,
    issuer: issuerDid,
    subject: subjectDid,
    credentialSubject,
    issuanceDate: issuanceDate.toISOString(),
    expirationDate: expirationDate?.toISOString(),
  };

  // Sign credential with KMS
  const credentialJson = JSON.stringify(credentialDataObj);
  const signature = await kmsClient.sign(Buffer.from(credentialJson));

  const proof = {
    type: 'KmsSignature2024',
    created: issuanceDate.toISOString(),
    proofPurpose: 'assertionMethod',
    verificationMethod: `${issuerDid}#kms-key`,
    jws: signature.toString('base64'),
  };

  await createVerifiableCredential({
    credential_id: credentialId,
    issuer_did: issuerDid,
    subject_did: subjectDid,
    credential_type: credentialType,
    credential_subject: credentialSubject,
    issuance_date: issuanceDate,
    expiration_date: expirationDate,
    proof,
  });

  return credentialId;
}

/**
 * Get financial credential template for role
 */
export function getFinancialCredentialTemplate(role: FinancialRole): {
  credentialType: string[];
  requiredFields: string[];
  optionalFields: string[];
} {
  const credentialType = FINANCIAL_CREDENTIAL_TYPES[role];

  const baseRequiredFields = ['role', 'appointmentDate', 'appointmentAuthority'];
  const baseOptionalFields = ['jurisdiction', 'termLength', 'expirationDate'];

  // Role-specific fields
  const roleSpecificFields: Record<FinancialRole, { required: string[]; optional: string[] }> = {
    ComptrollerGeneral: {
      required: [],
      optional: ['oversightScope', 'reportingAuthority'],
    },
    MonetaryComplianceOfficer: {
      required: [],
      optional: ['complianceScope', 'regulatoryFramework'],
    },
    CustodianOfDigitalAssets: {
      required: [],
      optional: ['custodyScope', 'securityLevel'],
    },
    FinancialAuditor: {
      required: [],
      optional: ['auditScope', 'certificationLevel'],
    },
    Treasurer: {
      required: [],
      optional: ['treasuryScope', 'authorityLevel'],
    },
    ChiefFinancialOfficer: {
      required: [],
      optional: ['cfoScope', 'executiveLevel'],
    },
  };

  const roleFields = roleSpecificFields[role];

  return {
    credentialType,
    requiredFields: [...baseRequiredFields, ...roleFields.required],
    optionalFields: [...baseOptionalFields, ...roleFields.optional],
  };
}

