import { describe, test, expect } from "bun:test";
import app from "../../src/api/server";

describe("API Server — Integration", () => {
  // -------------------------------------------------------------------
  // Teapot route (no auth required)
  // -------------------------------------------------------------------
  describe("GET /v1/teapot", () => {
    test("returns 418 I'm not a teapot", async () => {
      const res = await app.request("/v1/teapot");
      expect(res.status).toBe(418);
      const body: any = await res.json();
      expect(body.status).toBe(418);
      expect(body.message).toBe("I'm not a teapot");
      expect(body.successful).toBe(true);
    });

    test("returns JSON content type", async () => {
      const res = await app.request("/v1/teapot");
      expect(res.headers.get("content-type")).toContain("application/json");
    });
  });

  // -------------------------------------------------------------------
  // Not Found
  // -------------------------------------------------------------------
  describe("Not Found handling", () => {
    test("returns 404 for unknown routes", async () => {
      const res = await app.request("/v1/nonexistent");
      expect(res.status).toBe(404);
      const body: any = await res.json();
      expect(body.successful).toBe(false);
      expect(body.error).toBe("NotFound");
    });

    test("includes method and path in message", async () => {
      const res = await app.request("/v1/some/random/path", {
        method: "POST",
      });
      const body: any = await res.json();
      expect(body.message).toContain("POST");
      expect(body.message).toContain("/v1/some/random/path");
    });

    test("returns 404 for root path", async () => {
      const res = await app.request("/");
      expect(res.status).toBe(404);
    });
  });

  // -------------------------------------------------------------------
  // CORS
  // -------------------------------------------------------------------
  describe("CORS", () => {
    test("includes CORS headers", async () => {
      const res = await app.request("/v1/teapot", {
        headers: { Origin: "http://localhost:3000" },
      });
      // Hono's cors middleware should add access-control headers
      const acaoHeader = res.headers.get("access-control-allow-origin");
      expect(acaoHeader).toBeDefined();
    });

    test("handles OPTIONS preflight", async () => {
      const res = await app.request("/v1/teapot", {
        method: "OPTIONS",
        headers: {
          Origin: "http://localhost:3000",
          "Access-Control-Request-Method": "GET",
        },
      });
      // Should not be 404
      expect(res.status).toBeLessThan(400);
    });
  });

  // -------------------------------------------------------------------
  // Auth-protected routes (should reject without auth)
  // -------------------------------------------------------------------
  describe("Protected routes require authorization", () => {
    const protectedRoutes = [
      { method: "GET", path: "/v1/company/companies" },
      { method: "GET", path: "/v1/company/count" },
      { method: "GET", path: "/v1/credential/credentials/some-id" },
      { method: "POST", path: "/v1/credential/credentials" },
      { method: "GET", path: "/v1/role" },
      { method: "POST", path: "/v1/role" },
      { method: "GET", path: "/v1/user/users" },
    ];

    test.each(protectedRoutes)(
      "$method $path returns 401 without auth header",
      async ({ method, path }) => {
        const res = await app.request(path, { method });
        expect(res.status).toBe(401);
        const body: any = await res.json();
        expect(body.successful).toBe(false);
      },
    );

    test.each(protectedRoutes)(
      "$method $path returns error with invalid auth header",
      async ({ method, path }) => {
        const res = await app.request(path, {
          method,
          headers: { Authorization: "invalid-format" },
        });
        const body: any = await res.json();
        expect(body.successful).toBe(false);
      },
    );
  });

  // -------------------------------------------------------------------
  // Error handling
  // -------------------------------------------------------------------
  describe("Error handling", () => {
    test("ZodError returns 400 with error details", async () => {
      // POST to credentials without proper body should trigger a Zod error
      const res = await app.request("/v1/credential/credentials", {
        method: "POST",
        body: JSON.stringify({}),
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer invalid.token.here",
        },
      });
      // Will get auth error first, which is expected
      const body: any = await res.json();
      expect(body.successful).toBe(false);
    });
  });
});
