import { describe, it, expect, beforeAll, afterAll } from "vitest";
import express from "express";
import { app } from "../index.js";

// Note: These tests require Puppeteer/Chrome to be available
// For CI, use the Dockerfile which includes Chrome

const BASE = "http://localhost:3199";
let server: any;

beforeAll(async () => {
  process.env.API_KEYS = "test-key";
  process.env.PORT = "3199";
  // Import fresh to pick up env
  server = app.listen(3199);
  // Wait for browser init
  await new Promise((r) => setTimeout(r, 2000));
});

afterAll(async () => {
  server?.close();
});

describe("Auth", () => {
  it("rejects requests without API key", async () => {
    const res = await fetch(`${BASE}/v1/convert/html`, { method: "POST" });
    expect(res.status).toBe(401);
  });

  it("rejects invalid API key", async () => {
    const res = await fetch(`${BASE}/v1/convert/html`, {
      method: "POST",
      headers: { Authorization: "Bearer wrong-key" },
    });
    expect(res.status).toBe(403);
  });
});

describe("Health", () => {
  it("returns ok", async () => {
    const res = await fetch(`${BASE}/health`);
    expect(res.status).toBe(200);
    const data = await res.json();
    expect(data.status).toBe("ok");
  });
});

describe("HTML to PDF", () => {
  it("converts simple HTML", async () => {
    const res = await fetch(`${BASE}/v1/convert/html`, {
      method: "POST",
      headers: {
        Authorization: "Bearer test-key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ html: "<h1>Test</h1>" }),
    });
    expect(res.status).toBe(200);
    expect(res.headers.get("content-type")).toBe("application/pdf");
    const buf = await res.arrayBuffer();
    expect(buf.byteLength).toBeGreaterThan(100);
    // PDF magic bytes
    const header = new Uint8Array(buf.slice(0, 5));
    expect(String.fromCharCode(...header)).toBe("%PDF-");
  });

  it("rejects missing html field", async () => {
    const res = await fetch(`${BASE}/v1/convert/html`, {
      method: "POST",
      headers: {
        Authorization: "Bearer test-key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({}),
    });
    expect(res.status).toBe(400);
  });
});

describe("Markdown to PDF", () => {
  it("converts markdown", async () => {
    const res = await fetch(`${BASE}/v1/convert/markdown`, {
      method: "POST",
      headers: {
        Authorization: "Bearer test-key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ markdown: "# Hello\n\nWorld" }),
    });
    expect(res.status).toBe(200);
    expect(res.headers.get("content-type")).toBe("application/pdf");
  });
});

describe("Templates", () => {
  it("lists templates", async () => {
    const res = await fetch(`${BASE}/v1/templates`, {
      headers: { Authorization: "Bearer test-key" },
    });
    expect(res.status).toBe(200);
    const data = await res.json();
    expect(data.templates).toBeInstanceOf(Array);
    expect(data.templates.length).toBeGreaterThan(0);
  });

  it("renders invoice template", async () => {
    const res = await fetch(`${BASE}/v1/templates/invoice/render`, {
      method: "POST",
      headers: {
        Authorization: "Bearer test-key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        invoiceNumber: "TEST-001",
        date: "2026-02-14",
        from: { name: "Seller", email: "s@test.com" },
        to: { name: "Buyer", email: "b@test.com" },
        items: [{ description: "Widget", quantity: 2, unitPrice: 50, taxRate: 20 }],
      }),
    });
    expect(res.status).toBe(200);
    expect(res.headers.get("content-type")).toBe("application/pdf");
  });

  it("returns 404 for unknown template", async () => {
    const res = await fetch(`${BASE}/v1/templates/nonexistent/render`, {
      method: "POST",
      headers: {
        Authorization: "Bearer test-key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({}),
    });
    expect(res.status).toBe(404);
  });
});
