/**
 * Letters of Credence issuance automation
 * Template-based generation, digital signatures, Entra VerifiedID integration, status tracking
 */

import { createVerifiableCredential } from '@the-order/database';
import { EntraVerifiedIDClient } from '@the-order/auth';
import { KMSClient } from '@the-order/crypto';
import { getEnv } from '@the-order/shared';
import { getCredentialTemplateByName, renderCredentialFromTemplate } from '@the-order/database';
import { randomUUID } from 'crypto';

export interface LettersOfCredenceData {
  recipientDid: string;
  recipientName: string;
  recipientTitle: string;
  missionCountry: string;
  missionType: 'embassy' | 'consulate' | 'delegation' | 'mission';
  appointmentDate: Date;
  expirationDate?: Date;
  additionalClaims?: Record<string, unknown>;
}

export interface LettersOfCredenceStatus {
  credentialId: string;
  status: 'draft' | 'issued' | 'delivered' | 'revoked';
  issuedAt?: Date;
  deliveredAt?: Date;
  revokedAt?: Date;
}

/**
 * Issue Letters of Credence
 */
export async function issueLettersOfCredence(
  data: LettersOfCredenceData,
  kmsClient: KMSClient,
  useEntraVerifiedID = false
): 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 = data.expirationDate || new Date(issuanceDate.getTime() + 4 * 365 * 24 * 60 * 60 * 1000); // 4 years default

  // Try to get template
  const template = await getCredentialTemplateByName('letters-of-credence');
  const credentialSubject = template
    ? renderCredentialFromTemplate(template, {
        recipientDid: data.recipientDid,
        recipientName: data.recipientName,
        recipientTitle: data.recipientTitle,
        missionCountry: data.missionCountry,
        missionType: data.missionType,
        appointmentDate: data.appointmentDate.toISOString(),
        expirationDate: expirationDate.toISOString(),
        ...data.additionalClaims,
      })
    : {
        recipientDid: data.recipientDid,
        recipientName: data.recipientName,
        recipientTitle: data.recipientTitle,
        missionCountry: data.missionCountry,
        missionType: data.missionType,
        appointmentDate: data.appointmentDate.toISOString(),
        expirationDate: expirationDate.toISOString(),
        ...data.additionalClaims,
      };

  const credentialType = ['VerifiableCredential', 'DiplomaticCredential', 'LettersOfCredence'];

  // Use Entra VerifiedID if requested and configured
  if (useEntraVerifiedID && env.ENTRA_TENANT_ID && env.ENTRA_CLIENT_ID && env.ENTRA_CLIENT_SECRET) {
    const entraClient = new EntraVerifiedIDClient({
      tenantId: env.ENTRA_TENANT_ID,
      clientId: env.ENTRA_CLIENT_ID,
      clientSecret: env.ENTRA_CLIENT_SECRET,
      credentialManifestId: env.ENTRA_CREDENTIAL_MANIFEST_ID,
    });

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const issuanceRequest = await entraClient.issueCredential({
      claims: credentialSubject as any,
      subjectDid: data.recipientDid,
      pin: undefined,
      callbackUrl: undefined,
    } as any);

    // Store the issuance request reference
    credentialSubject.entraIssuanceRequest = issuanceRequest;
  }

  // Sign with KMS
  const credentialData = {
    id: credentialId,
    type: credentialType,
    issuer: issuerDid,
    subject: data.recipientDid,
    credentialSubject,
    issuanceDate: issuanceDate.toISOString(),
    expirationDate: expirationDate.toISOString(),
  };

  const credentialJson = JSON.stringify(credentialData);
  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: data.recipientDid,
    credential_type: credentialType,
    credential_subject: credentialSubject,
    issuance_date: issuanceDate,
    expiration_date: expirationDate,
    proof,
  });

  return credentialId;
}

/**
 * Track Letters of Credence status
 */
export async function trackLettersOfCredenceStatus(
  credentialId: string
): Promise<LettersOfCredenceStatus> {
  // In production, this would query a status tracking table
  // For now, return basic status
  return {
    credentialId,
    status: 'issued',
    issuedAt: new Date(),
  };
}

/**
 * Revoke Letters of Credence
 */
export async function revokeLettersOfCredence(
  credentialId: string,
  reason: string
): Promise<void> {
  const { revokeCredential } = await import('@the-order/database');
  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');
  }

  await revokeCredential({
    credential_id: credentialId,
    issuer_did: issuerDid,
    revocation_reason: reason,
  });
}

