/**
 * Batch credential issuance endpoint
 */

import { FastifyInstance } from 'fastify';
import { randomUUID } from 'crypto';
import { KMSClient } from '@the-order/crypto';
import { createVerifiableCredential } from '@the-order/database';
import { logCredentialAction } from '@the-order/database';
import { getEnv, authenticateJWT, requireRole } from '@the-order/shared';

export interface BatchIssuanceRequest {
  credentials: Array<{
    subject: string;
    credentialSubject: Record<string, unknown>;
    expirationDate?: string;
  }>;
}

export interface BatchIssuanceResponse {
  jobId: string;
  total: number;
  accepted: number;
  results: Array<{
    index: number;
    credentialId?: string;
    error?: string;
  }>;
}

/**
 * Register batch issuance endpoint
 */
export async function registerBatchIssuance(
  server: FastifyInstance,
  kmsClient: KMSClient
): Promise<void> {
  const env = getEnv();
  const issuerDid = env.VC_ISSUER_DID || (env.VC_ISSUER_DOMAIN ? `did:web:${env.VC_ISSUER_DOMAIN}` : undefined);

  server.post(
    '/vc/issue/batch',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'issuer')],
      schema: {
        body: {
          type: 'object',
          required: ['credentials'],
          properties: {
            credentials: {
              type: 'array',
              minItems: 1,
              maxItems: 100, // Limit batch size
              items: {
                type: 'object',
                required: ['subject', 'credentialSubject'],
                properties: {
                  subject: { type: 'string' },
                  credentialSubject: { type: 'object' },
                  expirationDate: { type: 'string', format: 'date-time' },
                },
              },
            },
          },
        },
        description: 'Batch issue verifiable credentials',
        tags: ['credentials'],
        response: {
          200: {
            type: 'object',
            properties: {
              jobId: { type: 'string' },
              total: { type: 'number' },
              accepted: { type: 'number' },
              results: {
                type: 'array',
                items: {
                  type: 'object',
                  properties: {
                    index: { type: 'number' },
                    credentialId: { type: 'string' },
                    error: { type: 'string' },
                  },
                },
              },
            },
          },
        },
      },
    },
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    async (request: any, reply: any) => {
      if (!issuerDid) {
        return reply.code(500).send({
          error: {
            code: 'CONFIGURATION_ERROR',
            message: 'VC_ISSUER_DID or VC_ISSUER_DOMAIN must be configured',
          },
        });
      }

      const { credentials } = request.body;
      const jobId = randomUUID();
      const results: BatchIssuanceResponse['results'] = [];
      let accepted = 0;

      // Get user ID for audit logging
      const user = (request as any).user;
      const userId = user?.id || user?.sub || null;

      // Process each credential
      for (let i = 0; i < credentials.length; i++) {
        const cred = credentials[i]!;
        try {
          const credentialId = randomUUID();
          const issuanceDate = new Date();
          const expirationDate = cred.expirationDate ? new Date(cred.expirationDate) : undefined;

          // Create credential data
          const credentialData = {
            id: credentialId,
            type: ['VerifiableCredential', 'IdentityCredential'],
            issuer: issuerDid,
            subject: cred.subject,
            credentialSubject: cred.credentialSubject,
            issuanceDate: issuanceDate.toISOString(),
            expirationDate: expirationDate?.toISOString(),
          };

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

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

          const credential = {
            ...credentialData,
            proof,
          };

          // Save to database
          await createVerifiableCredential({
            credential_id: credentialId,
            issuer_did: issuerDid,
            subject_did: cred.subject,
            credential_type: credential.type,
            credential_subject: cred.credentialSubject,
            issuance_date: issuanceDate,
            expiration_date: expirationDate,
            proof,
          });

          // Log audit action
          await logCredentialAction({
            credential_id: credentialId,
            issuer_did: issuerDid,
            subject_did: cred.subject,
            credential_type: credential.type,
            action: 'issued',
            performed_by: userId || undefined,
            metadata: { batchJobId: jobId, batchIndex: i },
            ip_address: request.ip,
            user_agent: request.headers['user-agent'],
          });

          results.push({
            index: i,
            credentialId,
          });
          accepted++;
        } catch (error) {
          results.push({
            index: i,
            error: error instanceof Error ? error.message : 'Unknown error',
          });
        }
      }

      return reply.send({
        jobId,
        total: credentials.length,
        accepted,
        results,
      });
    }
  );
}

