import type { AddressInfo } from "node:net";

import { afterEach, describe, expect, it } from "vitest";

import { closeStatusServer, createStatusServer, listenStatusServer } from "./status-server.js";

const openServers: ReturnType<typeof createStatusServer>[] = [];

afterEach(async () => {
  await Promise.all(openServers.splice(0).map((server) => closeStatusServer(server)));
});

async function startServer(ready: boolean): Promise<string> {
  const server = createStatusServer(() => ({ ready, ...(ready ? { botTag: "제노봇#7899" } : {}) }));
  openServers.push(server);
  await listenStatusServer(server, "127.0.0.1", 0);
  const address = server.address() as AddressInfo;
  return `http://127.0.0.1:${address.port}`;
}

describe("status server", () => {
  it("연결된 봇의 health 상태를 반환한다", async () => {
    const baseUrl = await startServer(true);
    const response = await fetch(`${baseUrl}/health`);

    expect(response.status).toBe(200);
    await expect(response.json()).resolves.toMatchObject({
      service: "xenosign-discord",
      status: "ok",
      discord: { connected: true, botTag: "제노봇#7899" },
    });
  });

  it("Discord 연결 전에는 health 요청에 503을 반환한다", async () => {
    const baseUrl = await startServer(false);
    const response = await fetch(`${baseUrl}/health`);

    expect(response.status).toBe(503);
    await expect(response.json()).resolves.toMatchObject({ status: "starting" });
  });

  it("알 수 없는 경로에는 404를 반환한다", async () => {
    const baseUrl = await startServer(true);
    const response = await fetch(`${baseUrl}/unknown`);

    expect(response.status).toBe(404);
  });
});
