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

const PREFIX = "enc:v1:";

function encryptionKey(): Buffer | null {
  const raw = process.env.FILE_ENCRYPTION_KEY;
  if (!raw) {
    if (process.env.NODE_ENV === "production") {
      console.warn(
        "FILE_ENCRYPTION_KEY is not set — sensitive URLs are stored unencrypted."
      );
    }
    return null;
  }
  return createHash("sha256").update(raw).digest();
}

/** Encrypt a sensitive URL/path for at-rest storage. Idempotent for already-encrypted values. */
export function encryptSensitiveUrl(value: string | null | undefined): string | null {
  if (!value) return null;
  if (value.startsWith(PREFIX)) return value;

  const key = encryptionKey();
  if (!key) return value;

  const iv = randomBytes(12);
  const cipher = createCipheriv("aes-256-gcm", key, iv);
  const encrypted = Buffer.concat([
    cipher.update(value, "utf8"),
    cipher.final(),
  ]);
  const tag = cipher.getAuthTag();
  return `${PREFIX}${iv.toString("base64url")}:${tag.toString("base64url")}:${encrypted.toString("base64url")}`;
}

/** Decrypt a stored sensitive URL. Passes through plaintext values. */
export function decryptSensitiveUrl(value: string | null | undefined): string | null {
  if (!value) return null;
  if (!value.startsWith(PREFIX)) return value;

  const key = encryptionKey();
  if (!key) {
    throw new Error("FILE_ENCRYPTION_KEY is required to read encrypted URLs");
  }

  const body = value.slice(PREFIX.length);
  const [ivB64, tagB64, dataB64] = body.split(":");
  if (!ivB64 || !tagB64 || !dataB64) {
    throw new Error("Corrupt encrypted URL payload");
  }

  const decipher = createDecipheriv(
    "aes-256-gcm",
    key,
    Buffer.from(ivB64, "base64url")
  );
  decipher.setAuthTag(Buffer.from(tagB64, "base64url"));
  const decrypted = Buffer.concat([
    decipher.update(Buffer.from(dataB64, "base64url")),
    decipher.final(),
  ]);
  return decrypted.toString("utf8");
}

export function isEncryptedSensitiveUrl(value: string | null | undefined): boolean {
  return Boolean(value?.startsWith(PREFIX));
}
