const crypto = require("crypto");

const ALGO = "aes-256-gcm";
const IV_LEN = 12;
const TAG_LEN = 16;

function getKey() {
  const raw = process.env.MS_TOKEN_ENCRYPTION_KEY || process.env.JWT_SECRET || "dev-only-key-change-me";
  return crypto.createHash("sha256").update(String(raw)).digest();
}

/**
 * Encrypt a Microsoft access or refresh token for storage in MySQL TEXT.
 */
function encryptMsToken(plain) {
  if (plain == null || plain === "") return null;
  const iv = crypto.randomBytes(IV_LEN);
  const cipher = crypto.createCipheriv(ALGO, getKey(), iv);
  const enc = Buffer.concat([cipher.update(String(plain), "utf8"), cipher.final()]);
  const tag = cipher.getAuthTag();
  return Buffer.concat([iv, tag, enc]).toString("base64");
}

/**
 * Decrypt a token stored by encryptMsToken.
 */
function decryptMsToken(stored) {
  if (stored == null || stored === "") return null;
  try {
    const buf = Buffer.from(stored, "base64");
    const iv = buf.subarray(0, IV_LEN);
    const tag = buf.subarray(IV_LEN, IV_LEN + TAG_LEN);
    const data = buf.subarray(IV_LEN + TAG_LEN);
    const decipher = crypto.createDecipheriv(ALGO, getKey(), iv);
    decipher.setAuthTag(tag);
    return Buffer.concat([decipher.update(data), decipher.final()]).toString("utf8");
  } catch (e) {
    console.error("msTokenCrypto decrypt failed:", e.message);
    return null;
  }
}

module.exports = { encryptMsToken, decryptMsToken };
