/**
 * Token Encryption Utility
 *
 * AES-256-GCM encryption/decryption for API tokens.
 * Stores tokens in a reversible (encrypted) format so the admin UI
 * can display full tokens with Show/Hide — while keeping them
 * encrypted at rest in the database.
 *
 * Uses the TOKEN_ENCRYPTION_KEY env var (32-byte hex string).
 * Falls back to a dev key if not set.
 */

import crypto from 'crypto';

const ALGORITHM = 'aes-256-gcm';
const IV_LENGTH = 16;
const AUTH_TAG_LENGTH = 16;

function getEncryptionKey(): Buffer {
  const keyHex = process.env.TOKEN_ENCRYPTION_KEY;
  if (keyHex && keyHex.length === 64) {
    return Buffer.from(keyHex, 'hex');
  }
  // Dev fallback — NOT for production
  console.warn('[tokenEncryption] TOKEN_ENCRYPTION_KEY not set or invalid. Using dev key. Set TOKEN_ENCRYPTION_KEY in production!');
  return crypto.createHash('sha256').update('mengo-api-token-encryption-dev-key').digest();
}

/**
 * Encrypt a plaintext string. Returns a hex-encoded string containing
 * iv + authTag + ciphertext.
 */
export function encryptToken(plaintext: string): string {
  const key = getEncryptionKey();
  const iv = crypto.randomBytes(IV_LENGTH);
  const cipher = crypto.createCipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });

  let encrypted = cipher.update(plaintext, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  const authTag = cipher.getAuthTag().toString('hex');

  // Format: iv:authTag:ciphertext (all hex)
  return `${iv.toString('hex')}:${authTag}:${encrypted}`;
}

/**
 * Decrypt a string encrypted by encryptToken. Returns the original plaintext.
 */
export function decryptToken(encrypted: string): string {
  const key = getEncryptionKey();
  const parts = encrypted.split(':');
  if (parts.length !== 3) {
    throw new Error('Invalid encrypted token format');
  }

  const iv = Buffer.from(parts[0], 'hex');
  const authTag = Buffer.from(parts[1], 'hex');
  const ciphertext = parts[2];

  const decipher = crypto.createDecipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });
  decipher.setAuthTag(authTag);

  let decrypted = decipher.update(ciphertext, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  return decrypted;
}