import { describe, it, expect } from "vitest";
import { encrypt, decrypt } from "../encrypt";

describe("encrypt / decrypt", () => {
  it("round-trips a short string", () => {
    const plain = "hello world";
    expect(decrypt(encrypt(plain))).toBe(plain);
  });

  it("round-trips an empty string", () => {
    expect(decrypt(encrypt(""))).toBe("");
  });

  it("round-trips a unicode string", () => {
    const plain = "café ☕ résumé";
    expect(decrypt(encrypt(plain))).toBe(plain);
  });

  it("round-trips a long string (API key-sized)", () => {
    const plain = "sk-proj-" + "a".repeat(128);
    expect(decrypt(encrypt(plain))).toBe(plain);
  });

  it("produces different ciphertexts for same input (random IV)", () => {
    const plain = "same input";
    const c1 = encrypt(plain);
    const c2 = encrypt(plain);
    expect(c1).not.toBe(c2);
    // but both decrypt to same value
    expect(decrypt(c1)).toBe(plain);
    expect(decrypt(c2)).toBe(plain);
  });

  it("ciphertext format is iv:authTag:encrypted (3 hex segments)", () => {
    const ct = encrypt("test");
    const parts = ct.split(":");
    expect(parts).toHaveLength(3);
    parts.forEach((p) => expect(p).toMatch(/^[0-9a-f]+$/));
  });

  it("throws on malformed ciphertext (wrong segments)", () => {
    expect(() => decrypt("notvalid")).toThrow("Invalid ciphertext format");
    expect(() => decrypt("a:b")).toThrow("Invalid ciphertext format");
  });

  it("throws on tampered ciphertext (auth tag mismatch)", () => {
    const ct = encrypt("sensitive");
    const parts = ct.split(":");
    // flip a byte in the encrypted payload
    const tampered = parts[0] + ":" + parts[1] + ":" + "00" + parts[2]!.slice(2);
    expect(() => decrypt(tampered)).toThrow();
  });
});
