import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { ChatPanel } from "@/components/ChatPanel";
import type { EditOperation } from "@/lib/chat/editOperations";

const chatState = vi.hoisted(() => ({
  messages: [] as Array<Record<string, unknown>>,
  sendMessage: vi.fn(),
  setMessages: vi.fn(),
  status: "ready",
}));

vi.mock("@ai-sdk/react", () => ({
  useChat: () => ({
    messages: chatState.messages,
    sendMessage: chatState.sendMessage,
    setMessages: chatState.setMessages,
    status: chatState.status,
  }),
}));

vi.mock("ai", () => ({
  DefaultChatTransport: vi.fn(function DefaultChatTransport() {
    return {};
  }),
}));

describe("ChatPanel", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    chatState.messages = [];
    chatState.status = "ready";
    Element.prototype.scrollIntoView = vi.fn();
  });

  it("previews editWorkflow tool calls instead of applying them immediately", async () => {
    const operations: EditOperation[] = [
      { type: "addNode", nodeType: "prompt", data: { prompt: "hello" } },
    ];
    const onApplyEdits = vi.fn();
    chatState.messages = [
      {
        id: "assistant-1",
        role: "assistant",
        parts: [
          {
            type: "tool-editWorkflow",
            state: "output-available",
            toolCallId: "edit-1",
            input: { operations, explanation: "Add a prompt node" },
          },
        ],
      },
    ];

    render(
      <ChatPanel
        isOpen
        onClose={vi.fn()}
        onApplyEdits={onApplyEdits}
      />
    );

    await screen.findByText("Operation preview");
    expect(onApplyEdits).not.toHaveBeenCalled();

    fireEvent.click(screen.getByText("Apply edits"));
    expect(onApplyEdits).toHaveBeenCalledWith(operations);
  });

  it("previews createWorkflow tool calls instead of building immediately", async () => {
    const onBuildWorkflow = vi.fn().mockResolvedValue(undefined);
    chatState.messages = [
      {
        id: "assistant-1",
        role: "assistant",
        parts: [
          {
            type: "tool-createWorkflow",
            state: "output-available",
            toolCallId: "create-1",
            input: { description: "Make a product photo workflow" },
          },
        ],
      },
    ];

    render(
      <ChatPanel
        isOpen
        onClose={vi.fn()}
        onBuildWorkflow={onBuildWorkflow}
      />
    );

    await screen.findByText("Candidate workflow");
    expect(onBuildWorkflow).not.toHaveBeenCalled();

    fireEvent.click(screen.getByText("Apply workflow"));
    await waitFor(() => {
      expect(onBuildWorkflow).toHaveBeenCalledWith("Make a product photo workflow");
    });
  });

  it("previews runCanvasAction tool calls instead of running immediately", async () => {
    const onRunAction = vi.fn();
    chatState.messages = [
      {
        id: "assistant-1",
        role: "assistant",
        parts: [
          {
            type: "tool-runCanvasAction",
            state: "output-available",
            toolCallId: "run-1",
            input: { action: "runSelected", explanation: "Run selected nodes" },
          },
        ],
      },
    ];

    render(
      <ChatPanel
        isOpen
        onClose={vi.fn()}
        onRunAction={onRunAction}
      />
    );

    await screen.findByText("Run preview");
    expect(onRunAction).not.toHaveBeenCalled();

    fireEvent.click(screen.getByText("Run now"));
    expect(onRunAction).toHaveBeenCalledWith("runSelected");
  });
});
