import { describe, test, expect } from "bun:test";
import { Hono } from "hono";

/**
 * Tests for the router aggregation pattern used throughout the app.
 * Each router imports route modules and mounts them.
 */
describe("Router pattern", () => {
  test("mounting multiple routes via Object.values pattern", () => {
    // Simulate the pattern used in companyRouter.ts
    const route1 = new Hono().get("/items", (c) => c.json({ route: "items" }));
    const route2 = new Hono().get("/count", (c) => c.json({ route: "count" }));

    const routes = { route1, route2 };
    const router = new Hono();
    Object.values(routes).map((r) => router.route("/", r));

    // Mount router under a prefix
    const app = new Hono();
    app.route("/v1/resource", router);

    return Promise.all([
      (async () => {
        const res = await app.request("/v1/resource/items");
        expect(res.status).toBe(200);
        const body: any = await res.json();
        expect(body.route).toBe("items");
      })(),
      (async () => {
        const res = await app.request("/v1/resource/count");
        expect(res.status).toBe(200);
        const body: any = await res.json();
        expect(body.route).toBe("count");
      })(),
    ]);
  });

  test("nested route parameters work correctly", async () => {
    const route = new Hono().get("/items/:id", (c) =>
      c.json({ id: c.req.param("id") }),
    );

    const router = new Hono();
    router.route("/", route);

    const app = new Hono();
    app.route("/v1/test", router);

    const res = await app.request("/v1/test/items/abc-123");
    expect(res.status).toBe(200);
    const body: any = await res.json();
    expect(body.id).toBe("abc-123");
  });

  test("error propagation through router chain", async () => {
    const route = new Hono().get("/fail", () => {
      throw new Error("Boom!");
    });

    const router = new Hono();
    router.route("/", route);

    const app = new Hono();
    app.onError((err, c) => c.json({ error: err.message, caught: true }, 500));
    app.route("/v1", router);

    const res = await app.request("/v1/fail");
    expect(res.status).toBe(500);
    const body: any = await res.json();
    expect(body.caught).toBe(true);
    expect(body.error).toBe("Boom!");
  });
});
