import { afterEach, describe, expect, it, vi } from "vitest";
import { FeishuReadinessError, probeFeishuApplication } from "../../src/connections/feishuReadiness.js";

describe("Feishu application readiness", () => {
  afterEach(() => {
    vi.unstubAllGlobals();
  });

  it("authenticates the app and verifies the exact bot identity", async () => {
    const fetchMock = vi.fn()
      .mockResolvedValueOnce(Response.json({ code: 0, tenant_access_token: "tenant-secret" }))
      .mockResolvedValueOnce(Response.json({ code: 0, bot: { open_id: "ou_expected" } }));
    vi.stubGlobal("fetch", fetchMock);

    await expect(probeFeishuApplication({
      appId: "cli_expected",
      appSecret: "app-secret",
      botOpenId: "ou_expected",
    })).resolves.toBeUndefined();

    expect(fetchMock).toHaveBeenCalledTimes(2);
    expect(fetchMock.mock.calls[1]?.[0]).toBe("https://open.feishu.cn/open-apis/bot/v3/info");
    expect(fetchMock.mock.calls[1]?.[1]).toMatchObject({
      method: "GET",
      redirect: "manual",
      headers: { authorization: "Bearer tenant-secret" },
    });
  });

  it("rejects a valid app credential paired with the wrong bot id", async () => {
    vi.stubGlobal("fetch", vi.fn()
      .mockResolvedValueOnce(Response.json({ code: 0, tenant_access_token: "tenant-secret" }))
      .mockResolvedValueOnce(Response.json({ code: 0, bot: { open_id: "ou_actual" } })));

    const failure = probeFeishuApplication({
      appId: "cli_expected",
      appSecret: "app-secret",
      botOpenId: "ou_wrong",
    });
    await expect(failure).rejects.toBeInstanceOf(FeishuReadinessError);
    await expect(failure).rejects.toMatchObject({
      code: "feishu_readiness_rejected",
      category: "provider_rejection",
    });
  });
});
