/**
 * Audit log — registro de acciones críticas.
 *
 * Convención fire-and-forget: auditar NUNCA debe romper la acción principal.
 * Si falla el INSERT, se logea en consola y la ejecución continúa.
 *
 * Acciones nombradas con convención `domain.verb`:
 *   - user.login, user.logout, user.password_changed
 *   - tenant.created, tenant.deleted
 *   - subscription.created, subscription.cancelled, subscription.reactivated,
 *     subscription.plan_changed
 *   - trial.started
 *   - price.updated
 *   - invoice.emitted_auto, invoice.emitted_manual, invoice.cancelled
 *   - fiel.uploaded, fiel.deleted
 *   - payment.recorded, payment.marked_paid_manually
 *
 * No logear GETs normales (dashboard, listar CFDIs) — demasiado volumen y sin
 * valor auditable. Log solo write operations con implicación fiscal/financiera.
 */
import type { Request } from 'express';
import { prisma } from '../config/database.js';

export interface AuditLogParams {
  userId?: string;
  tenantId?: string;
  action: string;
  entityType?: string;
  entityId?: string;
  metadata?: Record<string, any>;
}

export async function auditLog(params: AuditLogParams): Promise<void> {
  try {
    await prisma.auditLog.create({
      data: {
        userId: params.userId,
        tenantId: params.tenantId,
        action: params.action,
        entityType: params.entityType,
        entityId: params.entityId,
        metadata: (params.metadata ?? undefined) as any,
      },
    });
  } catch (error: any) {
    console.error('[Audit] Falló registrar evento:', params.action, error.message || error);
  }
}

/**
 * Helper para usar desde controllers — extrae user + tenant del `req` y enriquece
 * metadata con IP y user-agent automáticamente.
 */
export async function auditFromReq(
  req: Request,
  action: string,
  extra?: Omit<AuditLogParams, 'action'> & { metadata?: Record<string, any> },
): Promise<void> {
  const baseMetadata = {
    ip: req.ip,
    userAgent: req.get('user-agent'),
  };

  await auditLog({
    userId: req.user?.userId,
    tenantId: extra?.tenantId ?? req.user?.tenantId,
    entityType: extra?.entityType,
    entityId: extra?.entityId,
    metadata: { ...baseMetadata, ...(extra?.metadata ?? {}) },
    action,
  });
}
