import { describe, expect, it, vi } from "vitest";
import { type ChatReconnectActionsHost, reconnectPanel } from "../../../../../src/features/chat/application/connection/reconnect-actions";
import { createChatState } from "../../../../../src/features/chat/application/state/root-reducer";
import { createChatStateStore } from "../../../../../src/features/chat/application/state/store";

function createHost(overrides: Partial<ChatReconnectActionsHost> = {}) {
  const stateStore = createChatStateStore(createChatState());
  stateStore.dispatch({ type: "ui/panel-set", panel: "history" });
  stateStore.dispatch({
    type: "active-thread/resumed",
    approvalPolicyKnown: true,
    sandboxPolicyKnown: true,
    permissionProfileKnown: true,
    approvalPolicy: null,
    sandboxPolicy: null,
    activePermissionProfile: null,
    thread: { id: "thread" } as never,
    cwd: "/vault",
    model: null,
    reasoningEffort: null,
    serviceTier: null,
    approvalsReviewer: null,
  });
  stateStore.dispatch({
    type: "request/user-input-queued",
    input: {
      requestId: 7,
      params: {
        threadId: "thread",
        turnId: "turn",
        itemId: "input",
        questions: [],
        autoResolutionMs: null,
      },
    },
  });
  stateStore.dispatch({ type: "thread-list/applied", threads: [{ id: "thread" } as never] });
  const host: ChatReconnectActionsHost = {
    stateStore,
    invalidateConnectionWork: vi.fn(),
    invalidateThreadWork: vi.fn(),
    clearDeferredDiagnostics: vi.fn(),
    resetConnection: vi.fn(),
    setStatus: vi.fn(),
    ensureConnected: vi.fn().mockResolvedValue(undefined),
    isConnected: vi.fn(() => true),
    resumeThread: vi.fn().mockResolvedValue(undefined),
    addSystemMessage: vi.fn(),
    ...overrides,
  };
  return { host, stateStore };
}

describe("reconnectPanel", () => {
  it("resets local connection state before reconnecting and resumes the active thread", async () => {
    const { host, stateStore } = createHost();

    await reconnectPanel(host);

    expect(stateStore.getState().ui.toolbarPanel).toBeNull();
    expect(host.invalidateConnectionWork).toHaveBeenCalledOnce();
    expect(host.invalidateThreadWork).toHaveBeenCalledOnce();
    expect(host.clearDeferredDiagnostics).toHaveBeenCalledOnce();
    expect(host.resetConnection).toHaveBeenCalledOnce();
    expect(host.setStatus).toHaveBeenCalledWith("Reconnecting...", { kind: "connecting" });
    expect(stateStore.getState().requests.pendingUserInputs).toEqual([]);
    expect(stateStore.getState().threadList).toEqual({ listedThreads: [] });
    expect(host.ensureConnected).toHaveBeenCalledOnce();
    expect(host.resumeThread).toHaveBeenCalledWith("thread");
  });

  it("reports resume failures after reconnecting", async () => {
    const { host } = createHost({
      resumeThread: vi.fn().mockRejectedValue(new Error("resume failed")),
    });

    await reconnectPanel(host);

    expect(host.addSystemMessage).toHaveBeenCalledWith("resume failed");
  });
});
