/**
 * Tests for src/modules/pdf-utils/injectPdfMetadata.ts
 *
 * Uses pdf-lib to create a real in-memory PDF and verifies
 * metadata injection behavior.
 */

import { describe, test, expect } from "bun:test";
import { PDFDocument } from "pdf-lib";
import {
  injectPdfMetadata,
  type DownloadMetadata,
} from "../../src/modules/pdf-utils/injectPdfMetadata";

async function createBlankPdf(keywords?: string): Promise<Uint8Array> {
  const doc = await PDFDocument.create();
  doc.addPage([612, 792]);
  if (keywords) {
    doc.setKeywords([keywords]);
  }
  return doc.save();
}

describe("injectPdfMetadata", () => {
  test("injects required metadata keywords into a blank PDF", async () => {
    const pdfBytes = await createBlankPdf();
    const metadata: DownloadMetadata = {
      downloadedAt: "2026-03-01T12:00:00Z",
      downloadedById: "user-42",
    };

    const result = await injectPdfMetadata(pdfBytes, metadata);

    // Result should be a Uint8Array (valid PDF)
    expect(result).toBeInstanceOf(Uint8Array);
    expect(result.length).toBeGreaterThan(0);

    // Re-parse and check keywords
    const doc = await PDFDocument.load(result);
    const keywords = doc.getKeywords();
    expect(keywords).toContain("downloadedAt:2026-03-01T12:00:00Z");
    expect(keywords).toContain("downloadedById:user-42");
  });

  test("appends to existing keywords with separator", async () => {
    const existingKeywords = "createdBy:system; theme:default";
    const pdfBytes = await createBlankPdf(existingKeywords);
    const metadata: DownloadMetadata = {
      downloadedAt: "2026-03-01T12:00:00Z",
      downloadedById: "user-42",
    };

    const result = await injectPdfMetadata(pdfBytes, metadata);
    const doc = await PDFDocument.load(result);
    const keywords = doc.getKeywords() ?? "";

    // Should start with existing keywords
    expect(keywords).toContain("createdBy:system; theme:default");
    // Should have separator then new keywords
    expect(keywords).toContain("; downloadedAt:");
    expect(keywords).toContain("downloadedById:user-42");
  });

  test("includes optional name and email when provided", async () => {
    const pdfBytes = await createBlankPdf();
    const metadata: DownloadMetadata = {
      downloadedAt: "2026-03-01T12:00:00Z",
      downloadedById: "user-42",
      downloadedByName: "Jane Doe",
      downloadedByEmail: "jane@example.com",
    };

    const result = await injectPdfMetadata(pdfBytes, metadata);
    const doc = await PDFDocument.load(result);
    const keywords = doc.getKeywords() ?? "";

    expect(keywords).toContain("downloadedByName:Jane Doe");
    expect(keywords).toContain("downloadedByEmail:jane@example.com");
  });

  test("omits optional name/email when not provided", async () => {
    const pdfBytes = await createBlankPdf();
    const metadata: DownloadMetadata = {
      downloadedAt: "2026-03-01T12:00:00Z",
      downloadedById: "user-42",
    };

    const result = await injectPdfMetadata(pdfBytes, metadata);
    const doc = await PDFDocument.load(result);
    const keywords = doc.getKeywords() ?? "";

    expect(keywords).not.toContain("downloadedByName");
    expect(keywords).not.toContain("downloadedByEmail");
  });

  test("updates ModificationDate (save() applies current time by default)", async () => {
    const pdfBytes = await createBlankPdf();
    const metadata: DownloadMetadata = {
      downloadedAt: "2026-03-01T12:00:00Z",
      downloadedById: "user-42",
    };

    const before = Date.now();
    const result = await injectPdfMetadata(pdfBytes, metadata);
    const after = Date.now();
    const doc = await PDFDocument.load(result);
    const modDate = doc.getModificationDate();

    expect(modDate).toBeInstanceOf(Date);
    // pdf-lib's save() overrides ModificationDate with current time (updateMetadata defaults to true),
    // so we just verify the date is recent rather than matching downloadedAt exactly.
    expect(modDate!.getTime()).toBeGreaterThanOrEqual(before - 2000);
    expect(modDate!.getTime()).toBeLessThanOrEqual(after + 2000);
  });

  test("works with Buffer input", async () => {
    const pdfBytes = await createBlankPdf();
    const bufferInput = Buffer.from(pdfBytes);
    const metadata: DownloadMetadata = {
      downloadedAt: "2026-03-01T12:00:00Z",
      downloadedById: "user-1",
    };

    const result = await injectPdfMetadata(bufferInput, metadata);
    expect(result).toBeInstanceOf(Uint8Array);

    const doc = await PDFDocument.load(result);
    const keywords = doc.getKeywords() ?? "";
    expect(keywords).toContain("downloadedById:user-1");
  });
});
