import { createCipheriv, createDecipheriv, createHash, randomBytes } from "crypto";

const TOKEN_PREFIX = "chj_";
const TOKEN_ALGO = "aes-256-gcm";
const TOKEN_IV_BYTES = 12;

function getTokenEncryptionKey(): Buffer {
  const secret = process.env.JWT_SECRET?.trim();
  if (!secret) {
    throw new Error("JWT_SECRET 未配置，无法加密客户 API Key");
  }
  return createHash("sha256").update(secret, "utf8").digest();
}

export function hashServiceToken(rawToken: string): string {
  return createHash("sha256").update(rawToken, "utf8").digest("hex");
}

export function generateServiceToken(): string {
  return `${TOKEN_PREFIX}${randomBytes(24).toString("base64url")}`;
}

export function tokenKeyPrefix(rawToken: string): string {
  return rawToken.slice(0, Math.min(12, rawToken.length));
}

export function encryptServiceToken(rawToken: string): string {
  return encryptSecret(rawToken);
}

export function decryptServiceToken(ciphertext: string | null | undefined): string | null {
  return decryptSecret(ciphertext);
}

/** 通用 AES-GCM 密文（API Key、承运商密码等） */
export function encryptSecret(plaintext: string): string {
  const iv = randomBytes(TOKEN_IV_BYTES);
  const cipher = createCipheriv(TOKEN_ALGO, getTokenEncryptionKey(), iv);
  const encrypted = Buffer.concat([
    cipher.update(plaintext, "utf8"),
    cipher.final(),
  ]);
  const tag = cipher.getAuthTag();
  return Buffer.concat([iv, tag, encrypted]).toString("base64");
}

export function decryptSecret(ciphertext: string | null | undefined): string | null {
  if (!ciphertext) {
    return null;
  }
  const payload = Buffer.from(ciphertext, "base64");
  if (payload.length < TOKEN_IV_BYTES + 16 + 1) {
    return null;
  }
  const iv = payload.subarray(0, TOKEN_IV_BYTES);
  const tag = payload.subarray(TOKEN_IV_BYTES, TOKEN_IV_BYTES + 16);
  const encrypted = payload.subarray(TOKEN_IV_BYTES + 16);
  const decipher = createDecipheriv(TOKEN_ALGO, getTokenEncryptionKey(), iv);
  decipher.setAuthTag(tag);
  return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString(
    "utf8",
  );
}
