import { render, screen } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { ControlPanel } from "@/components/nodes/ControlPanel";
import { useWorkflowStore } from "@/store/workflowStore";
import type { WorkflowNode } from "@/types";

vi.mock("@/hooks/useInlineParameters", () => ({
  useInlineParameters: () => ({ inlineParametersEnabled: false }),
}));

vi.mock("@/components/nodes/ModelParameters", () => ({
  ModelParameters: () => <div data-testid="model-parameters" />,
}));

vi.mock("@/components/modals/ModelSearchDialog", () => ({
  ModelSearchDialog: () => null,
}));

function imageNode(): WorkflowNode {
  return {
    id: "image-1",
    type: "nanoBanana",
    selected: true,
    position: { x: 0, y: 0 },
    data: {
      inputImages: [],
      inputPrompt: "coffee spilled",
      outputImage: null,
      aspectRatio: "16:9",
      resolution: "1K",
      model: "nano-banana-pro",
      selectedModel: {
        provider: "newapiwg",
        modelId: "apiyi_nano_banana_2",
        displayName: "apiyi_nano_banana_2",
        capabilities: ["text-to-image", "image-to-image"],
      },
      parameters: { quality: "auto", size: "1024x1024" },
      useGoogleSearch: false,
      useImageSearch: false,
      status: "idle",
      error: null,
      imageHistory: [],
      selectedHistoryIndex: 0,
    },
  } as WorkflowNode;
}

function videoNode(): WorkflowNode {
  return {
    id: "video-1",
    type: "generateVideo",
    selected: true,
    position: { x: 0, y: 0 },
    data: {
      prompt: "camera pan",
      inputImage: null,
      outputVideo: null,
      selectedModel: {
        provider: "newapiwg",
        modelId: "video-model",
        displayName: "Video Model",
        capabilities: ["text-to-video"],
      },
      parameters: {},
      status: "idle",
      error: null,
      progress: 0,
    },
  } as WorkflowNode;
}

function llmNode(): WorkflowNode {
  return {
    id: "llm-1",
    type: "llmGenerate",
    selected: true,
    position: { x: 0, y: 0 },
    data: {
      inputPrompt: null,
      inputImages: [],
      inputVideos: [],
      outputText: null,
      provider: "newapiwg",
      model: "doubao-seed-2-0-lite-260428",
      temperature: 0.7,
      maxTokens: 2048,
      status: "idle",
      error: null,
    },
  } as WorkflowNode;
}

describe("ControlPanel", () => {
  const originalProviderMode = process.env.NEXT_PUBLIC_PROVIDER_MODE;

  beforeEach(() => {
    vi.clearAllMocks();
    useWorkflowStore.setState({
      nodes: [],
      edges: [],
      isRunning: false,
    });
  });

  afterEach(() => {
    if (originalProviderMode === undefined) {
      delete process.env.NEXT_PUBLIC_PROVIDER_MODE;
    } else {
      process.env.NEXT_PUBLIC_PROVIDER_MODE = originalProviderMode;
    }
  });

  it("does not render duplicate settings for image generation nodes controlled by the composer", () => {
    useWorkflowStore.setState({ nodes: [imageNode()] });

    const { container } = render(<ControlPanel />);

    expect(container).toBeEmptyDOMElement();
    expect(screen.queryByText("Generate Image Settings")).not.toBeInTheDocument();
    expect(screen.queryByText("1024x1024")).not.toBeInTheDocument();
  });

  it("keeps the right-side panel for generation nodes not yet owned by the composer", () => {
    useWorkflowStore.setState({ nodes: [videoNode()] });

    render(<ControlPanel />);

    expect(screen.getByText("Generate Video Settings")).toBeInTheDocument();
    expect(screen.getByTestId("model-parameters")).toBeInTheDocument();
  });

  it("hides provider labels in Popi provider mode", () => {
    process.env.NEXT_PUBLIC_PROVIDER_MODE = "popi";
    useWorkflowStore.setState({ nodes: [videoNode()] });

    render(<ControlPanel />);

    expect(screen.getByText("Video Model")).toBeInTheDocument();
    expect(screen.queryByText("Popi Models")).not.toBeInTheDocument();
  });

  it("does not render the side control panel for LLM nodes", () => {
    process.env.NEXT_PUBLIC_PROVIDER_MODE = "popi";
    useWorkflowStore.setState({ nodes: [llmNode()] });

    render(<ControlPanel />);

    expect(screen.queryByText("Provider")).not.toBeInTheDocument();
    expect(screen.queryByText("Model")).not.toBeInTheDocument();
    expect(screen.queryByText((content) => content.includes("0.70"))).not.toBeInTheDocument();
    expect(screen.queryByText((content) => content.includes("2,048"))).not.toBeInTheDocument();
    expect(screen.queryByText("模型配置")).not.toBeInTheDocument();
  });
});
