import type { Request, Response, NextFunction } from 'express';
import { prisma } from '../config/database.js';
import { isGlobalAdmin } from '../utils/global-admin.js';

async function requireGlobalAdmin(req: Request, res: Response): Promise<boolean> {
  const isAdmin = await isGlobalAdmin(req.user!.tenantId, req.user!.role, req.user!.userId);
  if (!isAdmin) {
    res.status(403).json({ message: 'Solo el administrador global puede consultar el audit log' });
  }
  return isAdmin;
}

/**
 * Lista eventos de audit con filtros opcionales. Admin global only.
 *
 * Query params:
 *   action      — filtra por action prefix (ej: "subscription." matches todas las subs)
 *   tenantId    — filtra a un tenant específico
 *   userId      — filtra a un user específico
 *   from, to    — rango de fechas (ISO)
 *   page, limit — paginación (default: 1, 50; max limit 200)
 */
export async function listAuditLog(req: Request, res: Response, next: NextFunction) {
  try {
    if (!(await requireGlobalAdmin(req, res))) return;

    const action = String(req.query.action || '').trim();
    const tenantId = String(req.query.tenantId || '').trim();
    const userId = String(req.query.userId || '').trim();
    const from = String(req.query.from || '').trim();
    const to = String(req.query.to || '').trim();
    const page = Math.max(1, parseInt(String(req.query.page || '1'), 10) || 1);
    const limit = Math.min(200, Math.max(1, parseInt(String(req.query.limit || '50'), 10) || 50));

    const where: any = {};
    if (action) where.action = { startsWith: action };
    if (tenantId) where.tenantId = tenantId;
    if (userId) where.userId = userId;
    if (from || to) {
      where.createdAt = {};
      if (from) where.createdAt.gte = new Date(from);
      if (to) where.createdAt.lte = new Date(to);
    }

    const [total, rows] = await Promise.all([
      prisma.auditLog.count({ where }),
      prisma.auditLog.findMany({
        where,
        orderBy: { createdAt: 'desc' },
        skip: (page - 1) * limit,
        take: limit,
      }),
    ]);

    // Enriquecer con user.email y tenant.nombre para display
    const userIds = [...new Set(rows.map(r => r.userId).filter(Boolean))] as string[];
    const tenantIds = [...new Set(rows.map(r => r.tenantId).filter(Boolean))] as string[];

    const [users, tenants] = await Promise.all([
      userIds.length
        ? prisma.user.findMany({ where: { id: { in: userIds } }, select: { id: true, email: true, nombre: true } })
        : [],
      tenantIds.length
        ? prisma.tenant.findMany({ where: { id: { in: tenantIds } }, select: { id: true, nombre: true, rfc: true } })
        : [],
    ]);

    const userMap = new Map(users.map(u => [u.id, u]));
    const tenantMap = new Map(tenants.map(t => [t.id, t]));

    const data = rows.map(r => ({
      ...r,
      user: r.userId ? userMap.get(r.userId) || null : null,
      tenant: r.tenantId ? tenantMap.get(r.tenantId) || null : null,
    }));

    res.json({
      data,
      page,
      limit,
      total,
      totalPages: Math.ceil(total / limit),
    });
  } catch (error) {
    next(error);
  }
}
