/**
 * Financial credential routes
 */

import { FastifyInstance } from 'fastify';
import { KMSClient } from '@the-order/crypto';
import { authenticateJWT, requireRole, getAuthorizationService } from '@the-order/shared';
import { issueFinancialCredential, getFinancialCredentialTemplate, FinancialRole, FINANCIAL_CREDENTIAL_TYPES } from './financial-credentials';
import { logCredentialAction } from '@the-order/database';
import { getEnv } from '@the-order/shared';

export async function registerFinancialCredentialRoutes(
  server: FastifyInstance,
  kmsClient: KMSClient
): Promise<void> {
  const env = getEnv();

  // Issue financial credential
  server.post(
    '/financial-credentials/issue',
    {
      preHandler: [authenticateJWT, requireRole('admin', 'financial-admin')],
      schema: {
        body: {
          type: 'object',
          required: ['subjectDid', 'role', 'appointmentDate', 'appointmentAuthority'],
          properties: {
            subjectDid: { type: 'string' },
            role: { type: 'string', enum: Object.keys(FINANCIAL_CREDENTIAL_TYPES) },
            appointmentDate: { type: 'string', format: 'date-time' },
            appointmentAuthority: { type: 'string' },
            jurisdiction: { type: 'string' },
            termLength: { type: 'number' },
            expirationDate: { type: 'string', format: 'date-time' },
            additionalClaims: { type: 'object' },
          },
        },
        description: 'Issue financial role credential',
        tags: ['financial-credentials'],
      },
    },
    async (request, reply) => {
      const body = request.body as {
        subjectDid: string;
        role: FinancialRole;
        appointmentDate: string;
        appointmentAuthority: string;
        jurisdiction?: string;
        termLength?: number;
        expirationDate?: string;
        additionalClaims?: Record<string, unknown>;
      };
      const user = (request as any).user;

      // Check authorization
      const authService = getAuthorizationService();
      const credentialType = FINANCIAL_CREDENTIAL_TYPES[body.role];
      const authCheck = await authService.canIssueCredential(user, credentialType);

      if (!authCheck.allowed) {
        return reply.code(403).send({ error: authCheck.reason || 'Not authorized' });
      }

      try {
        const credentialId = await issueFinancialCredential(
          body.subjectDid,
          {
            role: body.role,
            appointmentDate: new Date(body.appointmentDate),
            appointmentAuthority: body.appointmentAuthority,
            jurisdiction: body.jurisdiction,
            termLength: body.termLength,
            expirationDate: body.expirationDate ? new Date(body.expirationDate) : undefined,
            additionalClaims: body.additionalClaims,
          },
          kmsClient
        );

        // Log audit action
        await logCredentialAction({
          credential_id: credentialId,
          issuer_did: env.VC_ISSUER_DID || `did:web:${env.VC_ISSUER_DOMAIN}`,
          subject_did: body.subjectDid,
          credential_type: credentialType,
          action: 'issued',
          performed_by: user?.id || user?.sub || undefined,
          metadata: {
            role: body.role,
            appointmentAuthority: body.appointmentAuthority,
          },
        });

        return reply.send({ status: 'success', credentialId });
      } catch (error) {
        return reply.code(500).send({
          error: 'Failed to issue financial credential',
          message: error instanceof Error ? error.message : String(error),
        });
      }
    }
  );

  // Get financial credential template
  server.get(
    '/financial-credentials/template/:role',
    {
      preHandler: [authenticateJWT],
      schema: {
        params: {
          type: 'object',
          required: ['role'],
          properties: {
            role: { type: 'string', enum: Object.keys(FINANCIAL_CREDENTIAL_TYPES) },
          },
        },
        description: 'Get financial credential template',
        tags: ['financial-credentials'],
      },
    },
    async (request, reply) => {
      const { role } = request.params as { role: FinancialRole };

      const template = getFinancialCredentialTemplate(role);

      return reply.send({ role, template });
    }
  );

  server.log.info('Financial credential routes registered');
}
