import { createHmac, randomBytes, timingSafeEqual } from 'crypto';

type ActionGuardScope = 'purchase' | 'sales';

type ActionGuardPayload = {
  scope: ActionGuardScope;
  userId: string;
  iat: number;
  exp: number;
  nonce: string;
};

const ACTION_GUARD_SECRET = process.env.ACTION_GUARD_SECRET || 'dev-action-guard-secret-change-me';

function toBase64Url(input: string) {
  return Buffer.from(input, 'utf8').toString('base64url');
}

function fromBase64Url(input: string) {
  return Buffer.from(input, 'base64url').toString('utf8');
}

function signPayload(payloadB64: string) {
  return createHmac('sha256', ACTION_GUARD_SECRET).update(payloadB64).digest('base64url');
}

export function issueActionGuardToken(scope: ActionGuardScope, userId: string, ttlSeconds = 60 * 30) {
  const now = Date.now();
  const payload: ActionGuardPayload = {
    scope,
    userId: String(userId || '').trim(),
    iat: now,
    exp: now + Math.max(60 * 1000, ttlSeconds * 1000),
    nonce: randomBytes(12).toString('hex'),
  };

  const payloadB64 = toBase64Url(JSON.stringify(payload));
  const signature = signPayload(payloadB64);
  return `${payloadB64}.${signature}`;
}

export function verifyActionGuardToken(params: {
  token: string;
  scope: ActionGuardScope;
  userId: string;
}) {
  const token = String(params.token || '').trim();
  if (!token) return false;

  const dotIndex = token.lastIndexOf('.');
  if (dotIndex <= 0 || dotIndex >= token.length - 1) return false;

  const payloadB64 = token.slice(0, dotIndex);
  const receivedSignature = token.slice(dotIndex + 1);
  const expectedSignature = signPayload(payloadB64);

  const receivedBuffer = Buffer.from(receivedSignature, 'utf8');
  const expectedBuffer = Buffer.from(expectedSignature, 'utf8');
  if (receivedBuffer.length !== expectedBuffer.length) return false;
  if (!timingSafeEqual(receivedBuffer, expectedBuffer)) return false;

  let payload: ActionGuardPayload;
  try {
    payload = JSON.parse(fromBase64Url(payloadB64));
  } catch {
    return false;
  }

  const now = Date.now();
  if (!payload || payload.exp < now) return false;
  if (payload.scope !== params.scope) return false;
  if (String(payload.userId || '').trim() !== String(params.userId || '').trim()) return false;

  return true;
}
