/**
 * Judicial credential types and issuance
 * Registrar, Judicial Auditor, Provost Marshal, Judge, Court Clerk 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 JudicialRole =
  | 'Registrar'
  | 'JudicialAuditor'
  | 'ProvostMarshal'
  | 'Judge'
  | 'CourtClerk'
  | 'Bailiff'
  | 'CourtOfficer';

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

/**
 * Judicial credential type definitions
 */
export const JUDICIAL_CREDENTIAL_TYPES: Record<JudicialRole, string[]> = {
  Registrar: ['VerifiableCredential', 'JudicialCredential', 'RegistrarCredential'],
  JudicialAuditor: ['VerifiableCredential', 'JudicialCredential', 'JudicialAuditorCredential'],
  ProvostMarshal: ['VerifiableCredential', 'JudicialCredential', 'ProvostMarshalCredential'],
  Judge: ['VerifiableCredential', 'JudicialCredential', 'JudgeCredential'],
  CourtClerk: ['VerifiableCredential', 'JudicialCredential', 'CourtClerkCredential'],
  Bailiff: ['VerifiableCredential', 'JudicialCredential', 'BailiffCredential'],
  CourtOfficer: ['VerifiableCredential', 'JudicialCredential', 'CourtOfficerCredential'],
};

/**
 * Issue judicial credential
 */
export async function issueJudicialCredential(
  subjectDid: string,
  credentialData: JudicialCredentialData,
  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 = JUDICIAL_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 judicial credential template for role
 */
export function getJudicialCredentialTemplate(role: JudicialRole): {
  credentialType: string[];
  requiredFields: string[];
  optionalFields: string[];
} {
  const credentialType = JUDICIAL_CREDENTIAL_TYPES[role];

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

  // Role-specific fields
  const roleSpecificFields: Record<JudicialRole, { required: string[]; optional: string[] }> = {
    Registrar: {
      required: [],
      optional: ['registrarOffice', 'courtName'],
    },
    JudicialAuditor: {
      required: [],
      optional: ['auditScope', 'auditAuthority'],
    },
    ProvostMarshal: {
      required: [],
      optional: ['enforcementAuthority', 'jurisdiction'],
    },
    Judge: {
      required: [],
      optional: ['courtName', 'judgeLevel', 'specialization'],
    },
    CourtClerk: {
      required: [],
      optional: ['courtName', 'department'],
    },
    Bailiff: {
      required: [],
      optional: ['enforcementArea', 'authority'],
    },
    CourtOfficer: {
      required: [],
      optional: ['courtName', 'department', 'rank'],
    },
  };

  const roleFields = roleSpecificFields[role];

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

