/**
 * Automated judicial appointment credential issuance
 * Event-driven workflow: appointment → event → credential issuance → notification
 */

import { getEventBus, AppointmentEvents, CredentialEvents } from '@the-order/events';
import { issueJudicialCredential, type JudicialRole } from './judicial-credentials';
import { KMSClient } from '@the-order/crypto';
import { getNotificationService } from '@the-order/notifications';

export interface JudicialAppointmentData {
  userId: string;
  subjectDid: string;
  role: JudicialRole;
  appointmentDate: Date;
  appointmentAuthority: string;
  jurisdiction?: string;
  termLength?: number;
  expirationDate?: Date;
  recipientEmail?: string;
  recipientPhone?: string;
  recipientName?: string;
  additionalClaims?: Record<string, unknown>;
}

/**
 * Initialize automated judicial appointment credential issuance
 */
export async function initializeJudicialAppointmentIssuance(
  kmsClient: KMSClient
): Promise<void> {
  const eventBus = getEventBus();

  // Subscribe to appointment created events
  await eventBus.subscribe(AppointmentEvents.CREATED, async (data) => {
    const appointmentData = data as {
      userId: string;
      role: string;
      appointmentDate: string;
      appointmentAuthority: string;
      jurisdiction?: string;
      termLength?: number;
      expirationDate?: string;
      recipientEmail?: string;
      recipientPhone?: string;
      recipientName?: string;
      additionalClaims?: Record<string, unknown>;
    };

    // Check if it's a judicial appointment
    const judicialRoles: string[] = [
      'Registrar',
      'JudicialAuditor',
      'ProvostMarshal',
      'Judge',
      'CourtClerk',
      'Bailiff',
      'CourtOfficer',
    ];

    if (!judicialRoles.includes(appointmentData.role)) {
      return; // Not a judicial appointment
    }

    try {
      // Issue judicial credential
      const credentialId = await issueJudicialCredential(
        appointmentData.userId, // Using userId as subjectDid
        {
          role: appointmentData.role as JudicialRole,
          appointmentDate: new Date(appointmentData.appointmentDate),
          appointmentAuthority: appointmentData.appointmentAuthority,
          jurisdiction: appointmentData.jurisdiction,
          termLength: appointmentData.termLength,
          expirationDate: appointmentData.expirationDate
            ? new Date(appointmentData.expirationDate)
            : undefined,
          additionalClaims: appointmentData.additionalClaims,
        },
        kmsClient
      );

      // Publish credential issued event
      await eventBus.publish(CredentialEvents.ISSUED, {
        subjectDid: appointmentData.userId,
        credentialType: ['VerifiableCredential', 'JudicialCredential', `${appointmentData.role}Credential`],
        credentialId,
        issuedAt: new Date().toISOString(),
        recipientEmail: appointmentData.recipientEmail,
        recipientPhone: appointmentData.recipientPhone,
        recipientName: appointmentData.recipientName,
      });

      // Send notification
      if (appointmentData.recipientEmail) {
        const notificationService = getNotificationService();
        await notificationService.send({
          to: appointmentData.recipientEmail,
          type: 'email',
          message: `Dear ${appointmentData.recipientName || 'User'},

Your judicial appointment credential has been issued.

Role: ${appointmentData.role}
Appointment Authority: ${appointmentData.appointmentAuthority}
Appointment Date: ${appointmentData.appointmentDate}
Credential ID: ${credentialId}

You can view your credential at: ${process.env.CREDENTIALS_URL || 'https://theorder.org/credentials'}

Best regards,
The Order`,
          subject: 'Judicial Appointment Credential Issued',
        });
      }
    } catch (error) {
      console.error('Failed to issue judicial appointment credential:', error);
    }
  });

  // Subscribe to appointment confirmed events (for additional processing)
  await eventBus.subscribe(AppointmentEvents.CONFIRMED, async (data) => {
    // Additional processing when appointment is confirmed
    console.log('Judicial appointment confirmed:', data);
  });
}

/**
 * Manually trigger judicial appointment credential issuance
 */
export async function triggerJudicialAppointmentIssuance(
  appointmentData: JudicialAppointmentData,
  kmsClient: KMSClient
): Promise<string> {
  const credentialId = await issueJudicialCredential(
    appointmentData.subjectDid,
    {
      role: appointmentData.role,
      appointmentDate: appointmentData.appointmentDate,
      appointmentAuthority: appointmentData.appointmentAuthority,
      jurisdiction: appointmentData.jurisdiction,
      termLength: appointmentData.termLength,
      expirationDate: appointmentData.expirationDate,
      additionalClaims: appointmentData.additionalClaims,
    },
    kmsClient
  );

  const eventBus = getEventBus();
  await eventBus.publish(CredentialEvents.ISSUED, {
    subjectDid: appointmentData.subjectDid,
    credentialType: ['VerifiableCredential', 'JudicialCredential', `${appointmentData.role}Credential`],
    credentialId,
    issuedAt: new Date().toISOString(),
    recipientEmail: appointmentData.recipientEmail,
    recipientPhone: appointmentData.recipientPhone,
    recipientName: appointmentData.recipientName,
  });

  return credentialId;
}

