import * as crypto from 'crypto';

/**
 * Verify an HMAC-SHA256 signature for a webhook request.
 *
 * Signing payload format: `${timestamp}.${rawBody}` — the timestamp prefix prevents
 * replay attacks even if the body is captured.
 *
 * Header format: `X-Workflow-Signature: sha256=<hex digest>`
 *
 * Uses crypto.timingSafeEqual to prevent timing attacks.
 * Returns false (not throw) on length mismatch or any other comparison failure.
 */
export function verifyWebhookSignature(
  secret: string,
  timestamp: string,
  rawBody: Buffer | string,
  signatureHeader: string | undefined,
): boolean {
  if (!signatureHeader || !secret || !timestamp) return false;

  const body = typeof rawBody === 'string' ? Buffer.from(rawBody) : rawBody;
  const signingPayload = Buffer.concat([Buffer.from(`${timestamp}.`), body]);
  const expected = `sha256=${crypto
    .createHmac('sha256', secret)
    .update(signingPayload)
    .digest('hex')}`;

  const expectedBuf = Buffer.from(expected);
  const actualBuf = Buffer.from(signatureHeader);
  if (expectedBuf.length !== actualBuf.length) return false;

  try {
    return crypto.timingSafeEqual(expectedBuf, actualBuf);
  } catch {
    return false;
  }
}

/**
 * Helper for tests / manual signing — returns the X-Workflow-Signature header value.
 */
export function signWebhookPayload(
  secret: string,
  timestamp: string,
  rawBody: Buffer | string,
): string {
  const body = typeof rawBody === 'string' ? Buffer.from(rawBody) : rawBody;
  const signingPayload = Buffer.concat([Buffer.from(`${timestamp}.`), body]);
  return `sha256=${crypto
    .createHmac('sha256', secret)
    .update(signingPayload)
    .digest('hex')}`;
}
