import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';

export interface AuditDeps {
  createAuditLog: (entry: {
    userId: string;
    action: string;
    resource: string;
    resourceId?: string;
    details?: Record<string, unknown>;
  }) => Promise<void>;
}

export function registerAuditHook(app: FastifyInstance, deps: AuditDeps): void {
  app.addHook('onResponse', async (request: FastifyRequest, reply: FastifyReply) => {
    // Only audit mutating methods on authenticated requests
    if (request.userId === undefined) return;
    if (request.method === 'GET' || request.method === 'HEAD' || request.method === 'OPTIONS') return;

    const action = methodToAction(request.method);
    const { resource, resourceId } = parseRoute(request.url);

    const entry: Parameters<typeof deps.createAuditLog>[0] = {
      userId: request.userId,
      action,
      resource,
      details: {
        method: request.method,
        url: request.url,
        statusCode: reply.statusCode,
      },
    };
    if (resourceId !== undefined) {
      entry.resourceId = resourceId;
    }
    await deps.createAuditLog(entry);
  });
}

function methodToAction(method: string): string {
  switch (method) {
    case 'POST': return 'CREATE';
    case 'PUT':
    case 'PATCH': return 'UPDATE';
    case 'DELETE': return 'DELETE';
    default: return method;
  }
}

function parseRoute(url: string): { resource: string; resourceId: string | undefined } {
  const parts = url.split('?')[0]?.split('/').filter(Boolean) ?? [];
  // Pattern: /api/v1/resource/:id
  if (parts.length >= 3 && parts[0] === 'api') {
    return { resource: parts[2] ?? 'unknown', resourceId: parts[3] };
  }
  if (parts.length >= 1) {
    return { resource: parts[0] ?? 'unknown', resourceId: parts[1] };
  }
  return { resource: 'unknown', resourceId: undefined };
}
