import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import type { NodeDataType } from "@/types/flow";
import InspectionPanelHeader from "../components/InspectionPanelHeader";

// Mock EditableHeaderContent
const mockHandleSave = jest.fn();
const mockNameElement = <span>Test Node Name</span>;
const mockDescriptionElement = <div>Test Description</div>;

jest.mock("../components/EditableHeaderContent", () => {
  return jest.fn(() => ({
    containerRef: { current: null },
    handleSave: mockHandleSave,
    nameElement: mockNameElement,
    descriptionElement: mockDescriptionElement,
  }));
});

// Mock hooks
const mockHandleNodeClass = jest.fn();
const mockHandleOnNewValue = jest.fn();

jest.mock("@/CustomNodes/hooks/use-handle-node-class", () => ({
  __esModule: true,
  default: () => ({
    handleNodeClass: mockHandleNodeClass,
  }),
}));

jest.mock("@/CustomNodes/hooks/use-handle-new-value", () => ({
  __esModule: true,
  default: () => ({
    handleOnNewValue: mockHandleOnNewValue,
  }),
}));

// Mock stores
const mockSetNoticeData = jest.fn();
const mockSetSuccessData = jest.fn();

jest.mock("@/stores/alertStore", () => ({
  __esModule: true,
  default: (selector: any) =>
    selector({
      setNoticeData: mockSetNoticeData,
      setSuccessData: mockSetSuccessData,
    }),
}));

jest.mock("@/stores/shortcuts", () => ({
  useShortcutsStore: (selector: any) =>
    selector({
      shortcuts: [
        { name: "Docs", key: "d" },
        { name: "Code", key: "c" },
      ],
    }),
}));

// Mock components
jest.mock("@/components/common/genericIconComponent", () => ({
  __esModule: true,
  default: ({ name }: any) => <span data-testid={`icon-${name}`}>{name}</span>,
}));

jest.mock("@/components/common/shadTooltipComponent", () => ({
  __esModule: true,
  default: ({ children, content }: any) => (
    <div title={content}>{children}</div>
  ),
}));

jest.mock("@/components/ui/badge", () => ({
  Badge: ({ children, onClick, ...props }: any) => (
    <span onClick={onClick} {...props}>
      {children}
    </span>
  ),
}));

jest.mock("@/components/ui/button", () => ({
  Button: ({ children, onClick, ...props }: any) => (
    <button onClick={onClick} {...props}>
      {children}
    </button>
  ),
}));

jest.mock("../../nodeToolbarComponent/components/toolbar-button", () => ({
  ToolbarButton: ({ icon, onClick, dataTestId }: any) => (
    <button onClick={onClick} data-testid={dataTestId}>
      {icon}
    </button>
  ),
}));

jest.mock("@/modals/codeAreaModal", () => ({
  __esModule: true,
  default: ({ open, setOpen, setValue }: any) =>
    open ? (
      <div data-testid="code-modal">
        <button onClick={() => setOpen(false)} data-testid="close-code-modal">
          Close
        </button>
      </div>
    ) : null,
}));

jest.mock("@/customization/utils/custom-open-new-tab", () => ({
  customOpenNewTab: jest.fn(),
}));

jest.mock("@/utils/utils", () => ({
  cn: (...classes: any[]) => classes.filter(Boolean).join(" "),
}));

describe("InspectionPanelHeader", () => {
  const createMockData = (overrides = {}): NodeDataType => ({
    id: "test-node-123",
    type: "TestComponent",
    node: {
      display_name: "Test Node",
      description: "Test description",
      template: {},
      documentation: "https://docs.example.com",
      ...overrides,
    },
  });

  beforeEach(() => {
    jest.clearAllMocks();
    // Mock clipboard API with jest.fn()
    const mockWriteText = jest.fn().mockResolvedValue(undefined);
    Object.defineProperty(navigator, "clipboard", {
      value: {
        writeText: mockWriteText,
      },
      writable: true,
      configurable: true,
    });
  });

  describe("Basic Rendering", () => {
    it("should render node name from EditableHeaderContent", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      expect(screen.getByText("Test Node Name")).toBeInTheDocument();
    });

    it("should render description from EditableHeaderContent", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      expect(screen.getByText("Test Description")).toBeInTheDocument();
    });

    it("should render ID badge with truncated ID", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      expect(screen.getByText(/ID:/)).toBeInTheDocument();
    });

    it("should render edit button", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      expect(
        screen.getByTestId("edit-name-description-button"),
      ).toBeInTheDocument();
    });
  });

  describe("Documentation Button", () => {
    it("should render docs button when documentation exists", () => {
      const data = createMockData({
        documentation: "https://docs.example.com",
      });
      render(<InspectionPanelHeader data={data} />);

      expect(screen.getByTestId("docs-button-modal")).toBeInTheDocument();
    });

    it("should not render docs button when documentation is empty", () => {
      const data = createMockData({ documentation: "" });
      render(<InspectionPanelHeader data={data} />);

      expect(screen.queryByTestId("docs-button-modal")).not.toBeInTheDocument();
    });

    it("should open documentation when docs button is clicked", async () => {
      const user = userEvent.setup();
      const customOpenNewTab =
        require("@/customization/utils/custom-open-new-tab").customOpenNewTab;
      const data = createMockData({
        documentation: "https://docs.example.com",
      });

      render(<InspectionPanelHeader data={data} />);

      const docsButton = screen.getByTestId("docs-button-modal");
      await user.click(docsButton);

      expect(customOpenNewTab).toHaveBeenCalledWith("https://docs.example.com");
    });

    it("should show notice when docs not available", async () => {
      const user = userEvent.setup();
      const data = createMockData({ documentation: undefined });
      // Manually add docs button for testing
      const dataWithButton = { ...data };
      dataWithButton.node!.documentation = "";

      render(<InspectionPanelHeader data={data} />);

      // Since button won't render without docs, we test the callback logic
      // This is tested through the openDocs function
    });
  });

  describe("Copy ID Functionality", () => {
    it("should display truncated ID", () => {
      const data = createMockData();
      data.id = "very-long-id-12345-67890-abcdef";

      render(<InspectionPanelHeader data={data} />);

      // Should show last part after last dash
      expect(screen.getByText(/ID:.*abcdef/)).toBeInTheDocument();
    });

    it("should render ID badge", () => {
      const data = createMockData();

      render(<InspectionPanelHeader data={data} />);

      const badge = screen.getByText(/ID:/);
      expect(badge).toBeInTheDocument();
    });
  });

  describe("Edit Mode Toggle", () => {
    it("should show edit button in view mode", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      expect(
        screen.getByTestId("edit-name-description-button"),
      ).toBeInTheDocument();
      expect(screen.getByTestId("icon-PencilLine")).toBeInTheDocument();
    });

    it("should toggle to save button in edit mode", async () => {
      const user = userEvent.setup();
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      const editButton = screen.getByTestId("edit-name-description-button");
      await user.click(editButton);

      await waitFor(() => {
        expect(
          screen.getByTestId("save-name-description-button"),
        ).toBeInTheDocument();
        expect(screen.getByTestId("icon-Check")).toBeInTheDocument();
      });
    });

    it("should call handleSave when save button is clicked", async () => {
      const user = userEvent.setup();
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      const editButton = screen.getByTestId("edit-name-description-button");
      await user.click(editButton);

      const saveButton = await screen.findByTestId(
        "save-name-description-button",
      );
      await user.click(saveButton);

      expect(mockHandleSave).toHaveBeenCalled();
    });

    it("should show edit button with opacity 0 when not hovering", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      const editButton = screen.getByTestId("edit-name-description-button");
      expect(editButton).toHaveClass("opacity-0");
    });

    it("should show edit button with opacity 100 when hovering", async () => {
      const user = userEvent.setup();
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      const container = screen.getByTestId("panel-description");
      await user.hover(container);

      const editButton = screen.getByTestId("edit-name-description-button");
      expect(editButton).toHaveClass("opacity-100");
    });
  });

  describe("Close Functionality", () => {
    it("should call onClose when provided", async () => {
      const onClose = jest.fn();
      const data = createMockData();

      render(<InspectionPanelHeader data={data} onClose={onClose} />);

      // onClose would be called by parent component, not directly by header
      // This test verifies the prop is accepted
      expect(onClose).not.toHaveBeenCalled();
    });

    it("should work without onClose callback", () => {
      const data = createMockData();

      expect(() => {
        render(<InspectionPanelHeader data={data} />);
      }).not.toThrow();
    });
  });

  describe("Custom Component Detection", () => {
    it("should render code button for custom components", () => {
      const data = createMockData({
        type: "CustomComponent",
        edited: false,
        template: {
          code: { type: "code", value: "code" },
        },
      });

      render(<InspectionPanelHeader data={data} />);

      const codeButton = screen.getByTestId("edit-fields-button");
      expect(codeButton).toBeInTheDocument();
    });

    it("should render code button for non-custom components with code", () => {
      const data = createMockData({
        type: "RegularComponent",
        template: {
          code: { type: "code", value: "code" },
        },
      });

      render(<InspectionPanelHeader data={data} />);

      const codeButton = screen.getByTestId("edit-fields-button");
      expect(codeButton).toBeInTheDocument();
    });
  });

  describe("Edge Cases", () => {
    it("should handle component with minimal data", () => {
      const data = createMockData({ template: {} });

      expect(() => {
        render(<InspectionPanelHeader data={data} />);
      }).not.toThrow();
    });

    it("should handle very long IDs", () => {
      const data = createMockData();
      data.id =
        "extremely-long-id-that-should-be-truncated-properly-12345-67890-abcdef-ghijk";

      render(<InspectionPanelHeader data={data} />);

      expect(screen.getByText(/ID:/)).toBeInTheDocument();
    });
  });

  describe("Layout", () => {
    it("should have correct container structure", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      const container = screen.getByTestId("panel-description");
      expect(container).toHaveClass("flex");
      expect(container).toHaveClass("flex-col");
    });

    it("should render name in panel-name testid", () => {
      const data = createMockData();
      render(<InspectionPanelHeader data={data} />);

      expect(screen.getByTestId("panel-name")).toBeInTheDocument();
    });
  });
});
