/**
 * src/server/adminAuth.js
 *
 * Small, dependency-free HTTP auth middleware for admin/report endpoints
 * (/cleanup-test, /stale-workorders, /track-backfill, /create-wo-discovery, etc.).
 *
 * Accepts either:
 *   1. `Authorization: Bearer <ADMIN_TOKEN>` header, or
 *   2. `?token=<ADMIN_TOKEN>` query param (so it's usable from a browser bookmark)
 *
 * Configuration:
 *   ADMIN_TOKEN        Required. If unset, every admin request is refused.
 *
 * Intentionally NOT full IAM — this is a stop-gap for internal endpoints that
 * shouldn't be world-readable and shouldn't be one query flag away from doing
 * destructive work.
 */

import crypto from 'node:crypto';
import { logger } from '../utils/logger.js';

function timingSafeEq(a, b) {
  if (typeof a !== 'string' || typeof b !== 'string') return false;
  const ab = Buffer.from(a);
  const bb = Buffer.from(b);
  if (ab.length !== bb.length) return false;
  return crypto.timingSafeEqual(ab, bb);
}

/**
 * @param {object} [options]
 * @param {boolean} [options.allowInDev=true]  If true and NODE_ENV !== 'production',
 *   requests are allowed through even without a token (dev convenience). Set to
 *   false to enforce auth in every environment.
 */
export function requireAdmin(options = {}) {
  const { allowInDev = true } = options;

  return function adminAuthMiddleware(req, res, next) {
    const expected = process.env.ADMIN_TOKEN;

    if (!expected) {
      if (allowInDev && process.env.NODE_ENV !== 'production') {
        // Dev-mode escape hatch. Log every time so it doesn't stay silent.
        logger('adminAuth', `ADMIN_TOKEN unset — allowing ${req.method} ${req.originalUrl} (NODE_ENV=${process.env.NODE_ENV || 'undefined'})`, 'warn');
        return next();
      }
      logger('adminAuth', `ADMIN_TOKEN not configured — denying ${req.method} ${req.originalUrl}`, 'error');
      return res.status(503).send('Admin auth not configured (set ADMIN_TOKEN).');
    }

    let provided = null;
    const authHeader = req.headers.authorization;
    if (typeof authHeader === 'string' && authHeader.toLowerCase().startsWith('bearer ')) {
      provided = authHeader.slice(7).trim();
    }
    if (!provided && typeof req.query.token === 'string') {
      provided = req.query.token;
    }

    if (!provided || !timingSafeEq(provided, expected)) {
      logger('adminAuth', `Denied ${req.method} ${req.originalUrl} from ${req.ip}`, 'warn');
      return res.status(401).send('Unauthorized. Provide ADMIN_TOKEN via `Authorization: Bearer …` or `?token=…`.');
    }

    return next();
  };
}

export default requireAdmin;
