/**
 * Audit Middleware
 * 
 * Automatically logs audit events for all requests
 * Per DoD/MilSpec requirements (NIST SP 800-53: AU-2, AU-3)
 */

import { FastifyRequest, FastifyReply } from 'fastify'
import { logAuditEvent, logAuthentication, logDataAccess } from '../services/audit-logger'
import { logger } from '../lib/logger'

/**
 * Audit middleware - logs all requests for audit trail
 */
export async function auditMiddleware(
  request: FastifyRequest,
  reply: FastifyReply
): Promise<void> {
  // Skip audit logging for health checks and WebSocket upgrades
  if (request.url === '/health' || request.url === '/graphql-ws') {
    return
  }

  const user = (request as any).user
  const startTime = Date.now()

  // Log request
  try {
    // Determine event type based on request
    if (request.url === '/graphql') {
      // GraphQL request - log based on operation
      const body = request.body as any
      const operation = body?.operationName || 'UNKNOWN'
      
      await logAuditEvent({
        eventType: 'DATA_ACCESS',
        result: reply.statusCode < 400 ? 'SUCCESS' : 'FAILURE',
        userId: user?.id,
        userName: user?.name,
        userRole: user?.role,
        ipAddress: request.ip,
        userAgent: request.headers['user-agent'],
        action: `GRAPHQL_${operation}`,
        details: {
          query: body?.query?.substring(0, 200), // Log first 200 chars of query
          variables: body?.variables ? 'PRESENT' : 'NONE', // Don't log full variables
        },
      })
    } else {
      // Regular HTTP request
      await logAuditEvent({
        eventType: 'DATA_ACCESS',
        result: reply.statusCode < 400 ? 'SUCCESS' : 'FAILURE',
        userId: user?.id,
        userName: user?.name,
        userRole: user?.role,
        ipAddress: request.ip,
        userAgent: request.headers['user-agent'],
        action: `${request.method} ${request.url}`,
        details: {
          statusCode: reply.statusCode,
          responseTime: Date.now() - startTime,
        },
      })
    }
  } catch (error) {
    // Don't fail the request if audit logging fails, but log the error
    logger.error('Failed to log audit event', { error, request: request.url })
  }
}

