import "@testing-library/jest-dom";
import React from "react";
import { act, render, screen } from "@testing-library/react";

import { GlobalChatbox } from "./GlobalChatbox";

const createSession = jest.fn();
let mockCurrentProjectId = "project-1";

jest.mock("@refinedev/core", () => ({
  useNotification: () => ({ open: jest.fn() }),
}));

jest.mock("@/lib/chatModels", () => ({
  fetchAgentModels: jest.fn(() => new Promise(() => {})),
}));

jest.mock("@/store/projectStore", () => ({
  useProjectStore: (selector: (state: { currentProjectId: string }) => unknown) =>
    selector({ currentProjectId: mockCurrentProjectId }),
}));

jest.mock("./globalChatboxVoice", () => ({
  useSpeechSynthesis: () => ({
    speechState: "idle",
    speakingMessageId: null,
    speak: jest.fn(),
    pause: jest.fn(),
    resume: jest.fn(),
    stop: jest.fn(),
    isSupported: true,
  }),
  useSpeechRecognition: () => ({
    isListening: false,
    start: jest.fn(),
    stop: jest.fn(),
    isSupported: true,
  }),
}));

jest.mock("./hooks/useAgentToolActions", () => ({
  useAgentToolActions: () => jest.fn(),
}));

jest.mock("./hooks/useAgentChatSession", () => ({
  useAgentChatSession: () => ({
    messages: [],
    chatSessions: [],
    activeSessionId: undefined,
    isHydrating: false,
    loadingSessionId: null,
    isStreaming: false,
    sessionTitle: "新会话",
    sendPrompt: jest.fn(),
    createBranch: jest.fn(),
    abort: jest.fn(),
    replyPermission: jest.fn(),
    replyQuestion: jest.fn(),
    rejectQuestion: jest.fn(),
    createSession,
    renameSession: jest.fn(),
    removeSession: jest.fn(),
    switchSession: jest.fn(),
  }),
}));

jest.mock("./AgentHeader", () => ({
  AgentHeader: () => <div>Agent header</div>,
}));

jest.mock("./AgentHistoryPanel", () => ({
  AgentHistoryPanel: () => <div>History</div>,
}));

jest.mock("./AgentWorkspace", () => ({
  AgentWorkspace: () => <div data-testid="agent-workspace">Workspace</div>,
}));

jest.mock("./AgentComposer", () => ({
  AgentComposer: React.forwardRef(function MockAgentComposer() {
    return <div>Composer</div>;
  }),
}));

jest.mock("./GlobalChatboxParts", () => ({
  Blob: () => null,
}));

describe("GlobalChatbox lifecycle", () => {
  beforeEach(() => {
    jest.useFakeTimers();
    createSession.mockClear();
    mockCurrentProjectId = "project-1";
  });

  afterEach(() => {
    jest.runOnlyPendingTimers();
    jest.useRealTimers();
  });

  it("keeps content mounted and preserves the session across close and reopen", async () => {
    const { rerender } = render(<GlobalChatbox open onClose={jest.fn()} />);

    act(() => jest.runOnlyPendingTimers());
    expect(createSession).toHaveBeenCalledTimes(1);
    expect(screen.getByTestId("agent-workspace")).toBeInTheDocument();

    rerender(<GlobalChatbox open={false} onClose={jest.fn()} />);
    act(() => jest.advanceTimersByTime(300));

    expect(screen.getByTestId("agent-workspace")).toBeInTheDocument();

    rerender(<GlobalChatbox open onClose={jest.fn()} />);
    act(() => jest.runOnlyPendingTimers());

    expect(createSession).toHaveBeenCalledTimes(1);

    mockCurrentProjectId = "project-2";
    rerender(<GlobalChatbox open onClose={jest.fn()} />);
    act(() => jest.runOnlyPendingTimers());

    expect(createSession).toHaveBeenCalledTimes(2);
  });
});
