import { beforeEach, describe, expect, it } from "bun:test";
import { Hono } from "hono";
import { categoryRoutes } from "../../src/server/routes/categories.ts";
import { itemRoutes } from "../../src/server/routes/items.ts";
import { createTestDb } from "../helpers/db.ts";

async function createTestApp() {
	const { db, userId } = await createTestDb();
	const app = new Hono();

	// Inject test DB and userId into context for all routes
	app.use("*", async (c, next) => {
		c.set("db", db);
		c.set("userId", userId);
		await next();
	});

	app.route("/api/categories", categoryRoutes);
	app.route("/api/items", itemRoutes);
	return { app, db, userId };
}

describe("Category Routes", () => {
	let app: Hono;

	beforeEach(async () => {
		const testApp = await createTestApp();
		app = testApp.app;
	});

	it("POST /api/categories creates category", async () => {
		const res = await app.request("/api/categories", {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ name: "Shelter", icon: "tent" }),
		});

		expect(res.status).toBe(201);
		const body = await res.json();
		expect(body.name).toBe("Shelter");
		expect(body.icon).toBe("tent");
		expect(body.id).toBeGreaterThan(0);
	});

	it("GET /api/categories returns all categories", async () => {
		const res = await app.request("/api/categories");
		expect(res.status).toBe(200);
		const body = await res.json();
		expect(Array.isArray(body)).toBe(true);
		// At minimum, Uncategorized is seeded
		expect(body.length).toBeGreaterThanOrEqual(1);
	});

	it("DELETE /api/categories/:id reassigns items", async () => {
		// Create category
		const catRes = await app.request("/api/categories", {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ name: "Shelter", icon: "tent" }),
		});
		const cat = await catRes.json();

		// Create item in that category
		await app.request("/api/items", {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ name: "Tent", categoryId: cat.id }),
		});

		// Delete the category
		const delRes = await app.request(`/api/categories/${cat.id}`, {
			method: "DELETE",
		});
		expect(delRes.status).toBe(200);

		// Verify items are now in Uncategorized
		const itemsRes = await app.request("/api/items");
		const items = await itemsRes.json();
		const tent = items.find((i: any) => i.name === "Tent");
		expect(tent.categoryId).toBe(1);
	});

	it("DELETE /api/categories/1 returns 400 (cannot delete Uncategorized)", async () => {
		const res = await app.request("/api/categories/1", {
			method: "DELETE",
		});

		expect(res.status).toBe(400);
		const body = await res.json();
		expect(body.error).toContain("Uncategorized");
	});
});
