import { describe, expect, it } from "vitest";
import { encryptBackup, decryptBackup } from "../src/main/backup-crypto";

describe("backup-crypto", () => {
  it("encrypts and decrypts a round-trip correctly", () => {
    const original = JSON.stringify({
      version: 2,
      settings: { token: "my-secret-api-key", outputDir: "C:\\Downloads" },
      session: { packages: {}, items: {} },
      history: [{ id: "h1", name: "Test" }]
    });

    const encrypted = encryptBackup(original);
    const decrypted = decryptBackup(encrypted);
    expect(decrypted).toBe(original);
  });

  it("produces binary output that is not plaintext readable", () => {
    const secret = "super-secret-token-12345";
    const plaintext = JSON.stringify({ settings: { token: secret } });
    const encrypted = encryptBackup(plaintext);

    expect(encrypted.toString("utf8")).not.toContain(secret);
    expect(encrypted.toString("latin1")).not.toContain(secret);
  });

  it("starts with the MDD1 magic bytes", () => {
    const encrypted = encryptBackup("test");
    expect(encrypted.subarray(0, 4).toString("utf8")).toBe("MDD1");
  });

  it("produces different ciphertext for the same input (random IV)", () => {
    const plaintext = "same input data";
    const a = encryptBackup(plaintext);
    const b = encryptBackup(plaintext);
    expect(a.equals(b)).toBe(false);
    expect(decryptBackup(a)).toBe(plaintext);
    expect(decryptBackup(b)).toBe(plaintext);
  });

  it("throws on truncated data", () => {
    const encrypted = encryptBackup("test data");
    const truncated = encrypted.subarray(0, 10);
    expect(() => decryptBackup(truncated)).toThrow();
  });

  it("throws on corrupted ciphertext", () => {
    const encrypted = encryptBackup("test data");
    const corrupted = Buffer.from(encrypted);
    corrupted[corrupted.length - 1] ^= 0xff;
    expect(() => decryptBackup(corrupted)).toThrow();
  });

  it("throws on wrong magic bytes", () => {
    const encrypted = encryptBackup("test data");
    const wrongMagic = Buffer.from(encrypted);
    wrongMagic[0] = 0x00;
    expect(() => decryptBackup(wrongMagic)).toThrow(/Signatur/);
  });

  it("throws on empty buffer", () => {
    expect(() => decryptBackup(Buffer.alloc(0))).toThrow();
  });

  it("handles large payloads", () => {
    const large = JSON.stringify({ data: "x".repeat(1_000_000) });
    const encrypted = encryptBackup(large);
    const decrypted = decryptBackup(encrypted);
    expect(decrypted).toBe(large);
  });

  it("handles unicode content", () => {
    const unicode = JSON.stringify({ name: "Ünïcödé 日本語 🎉", path: "C:\\Benutzer\\Ö" });
    const encrypted = encryptBackup(unicode);
    expect(decryptBackup(encrypted)).toBe(unicode);
  });

  it("handles empty string round-trip", () => {
    const encrypted = encryptBackup("");
    expect(decryptBackup(encrypted)).toBe("");
  });
});
