import { createHmac, timingSafeEqual } from 'crypto';
import type { Request, Response, NextFunction } from 'express';

const SHARED_SECRET  = process.env.NOTETOQUOTE_SHARED_SECRET ?? '';
const MAX_AGE_SECONDS = 300;

export function hmacMiddleware(req: Request, res: Response, next: NextFunction): void {
  if (!SHARED_SECRET) {
    // Fail CLOSED — never allow requests through if secret is not configured
    res.status(503).json({ error: 'hmac_not_configured' });
    return;
  }

  const timestampHeader = req.headers['x-ntq-timestamp'] as string | undefined;
  const signatureHeader = req.headers['x-ntq-signature'] as string | undefined;

  if (!timestampHeader || !signatureHeader) {
    res.status(401).json({ error: 'missing_signature' });
    return;
  }

  const timestamp = parseInt(timestampHeader, 10);
  if (isNaN(timestamp)) {
    res.status(401).json({ error: 'invalid_timestamp' });
    return;
  }

  if (Math.abs(Date.now() / 1000 - timestamp) > MAX_AGE_SECONDS) {
    res.status(401).json({ error: 'request_expired' });
    return;
  }

  const rawBody  = (req as any).rawBody as string | undefined;
  const payload  = rawBody ?? JSON.stringify(req.body);
  const expected = createHmac('sha256', SHARED_SECRET)
    .update(`${timestamp}.${payload}`)
    .digest('hex');

  let valid = false;
  try {
    valid = timingSafeEqual(
      Buffer.from(signatureHeader, 'hex'),
      Buffer.from(expected, 'hex'),
    );
  } catch {
    valid = false;
  }

  if (!valid) {
    res.status(401).json({ error: 'invalid_signature' });
    return;
  }

  next();
}
