import { beforeEach, describe, expect, test, vi } from "vitest";

import { useChatAgent } from "./use-chat-agent";

const mocks = vi.hoisted(() => ({
  agent: {
    error: undefined,
    historyReady: true,
    messages: [],
    sendMessage: vi.fn(() => Promise.resolve()),
    status: "idle" as const,
  },
  organization: {} as { error?: Error; organizationId?: string },
  useFlueAgent: vi.fn(),
}));

vi.mock("@flue/react", () => ({
  useFlueAgent: mocks.useFlueAgent,
}));
vi.mock("@/hooks/use-personal-organization", () => ({
  usePersonalOrganization: () => mocks.organization,
}));

describe("useChatAgent", () => {
  beforeEach(() => {
    mocks.organization = {};
    mocks.agent.sendMessage.mockClear();
    mocks.useFlueAgent.mockReset();
    mocks.useFlueAgent.mockReturnValue(mocks.agent);
  });

  test("does not use the agent before organization bootstrap completes", async () => {
    const chat = useChatAgent();

    expect(mocks.useFlueAgent).toHaveBeenCalledWith({
      id: undefined,
      live: "sse",
      name: "zopu",
    });
    expect(chat.status).toBe("connecting");
    await expect(chat.sendMessage("too early")).rejects.toThrow(
      "Personal organization is still being prepared"
    );
    expect(mocks.agent.sendMessage).not.toHaveBeenCalled();
  });

  test("uses the ensured organization id for the agent session", async () => {
    mocks.organization = { organizationId: "org-a" };

    const chat = useChatAgent();
    expect(mocks.useFlueAgent).toHaveBeenCalledWith({
      id: "org-a",
      live: "sse",
      name: "zopu",
    });

    await chat.sendMessage("ready");
    expect(mocks.agent.sendMessage).toHaveBeenCalledWith("ready");
  });
});
