/* @vitest-environment node */

import { describe, it, expect } from "vitest";
import { jsonError, withErrorHandling, badRequest, json } from "./errors.js";

it("json sets Cache-Control: no-store by default (RHL-006)", async () => {
	const res = json({ ok: true }, 200);
	expect(res.headers.get("Cache-Control")).toBe("no-store");
});

describe("lib/api/errors", () => {
	it("jsonError returns the standardized error shape without details", async () => {
		const res = jsonError(401, "AUTH_UNAUTHENTICATED", "Unauthorized");

		expect(res.status).toBe(401);
		expect(await res.json()).toEqual({
			error: { message: "Unauthorized", code: "AUTH_UNAUTHENTICATED" },
		});
	});

	it("jsonError includes details when provided", async () => {
		const res = jsonError(
			400,
			"VALIDATION_MISSING_PARAM",
			"Missing required route parameter(s)",
			{ params: ["branch"] }
		);

		expect(res.status).toBe(400);
		expect(await res.json()).toEqual({
			error: {
				message: "Missing required route parameter(s)",
				code: "VALIDATION_MISSING_PARAM",
				details: { params: ["branch"] },
			},
		});
	});

	it("withErrorHandling converts ApiError into a standardized response", async () => {
		// The wrapped handler throws an expected error (ApiError).
		// The wrapper must convert it into { error: { message, code } } with status 400.
		const handler = withErrorHandling(async () => {
			throw badRequest("VALIDATION_TEST", "Bad Request");
		});

		const res = await handler();

		expect(res.status).toBe(400);
		expect(await res.json()).toEqual({
			error: { message: "Bad Request", code: "VALIDATION_TEST" },
		});
	});

	it("withErrorHandling converts unknown errors into a safe 500 response", async () => {
		// Unknown errors must never leak internal messages/stacks.
		// We always return a generic 500 payload.
		const handler = withErrorHandling(async () => {
			throw new Error("boom");
		});

		const res = await handler();

		expect(res.status).toBe(500);
		expect(await res.json()).toEqual({
			error: {
				message: "Internal server error",
				code: "INTERNAL_SERVER_ERROR",
			},
		});
	});
});
