import { AsyncLocalStorage } from 'async_hooks';
import type { NextFunction, Request, Response } from 'express';

/**
 * Rubro elegido en el selector del sidebar, por request.
 *
 * El frontend lo manda en el header `x-rubro-id` en todas las llamadas. Acá
 * queda en un contexto asíncrono para que `alcanceSucursalUsuario` lo lea sin
 * que cada uno de sus ~26 llamadores tenga que recibirlo y pasarlo: así el
 * selector recorta listados, reportes y dashboards de una sola vez (antes sólo
 * lo respetaban las pantallas que recibían `rubro_id` a mano).
 * Ver docs/plan-rubros-multi-sucursal.md.
 */
export const RUBRO_HEADER = 'x-rubro-id';

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

const contexto = new AsyncLocalStorage<{ rubroId: string | null }>();

export function correrConRubro<T>(rubroId: string | null, fn: () => T): T {
  return contexto.run({ rubroId }, fn);
}

/** `null` = sin rubro elegido ("Todos los rubros") o fuera de un request. */
export function rubroDelRequest(): string | null {
  return contexto.getStore()?.rubroId ?? null;
}

/** Sólo acepta un UUID: cualquier otra cosa (vacío, "todos", basura) es "sin rubro". */
export function rubroContextMiddleware(req: Request, _res: Response, next: NextFunction): void {
  const raw = req.headers?.[RUBRO_HEADER];
  const valor = Array.isArray(raw) ? raw[0] : raw;
  const rubroId = typeof valor === 'string' && UUID_RE.test(valor) ? valor : null;
  correrConRubro(rubroId, next);
}
