import React from "react";
import { DynamicTabs } from "./index";

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

jest.mock("next/link", () => {
  const MockNextLink = ({ children, href, className, ...props }: any) => (
    <a href={href} className={className} {...props}>
      {children}
    </a>
  );

  MockNextLink.displayName = "MockNextLink";

  return MockNextLink;
});

jest.mock("framer-motion", () => ({
  AnimatePresence: ({ children }: any) => <>{children}</>,
  motion: {
    div: ({ children, animate }: any) => (
      <div data-testid="motion-div" style={{ opacity: animate?.opacity }}>
        {children}
      </div>
    ),
  },
}));

jest.mock("@shared/components/collapse", () => ({
  Collapse: ({ open, children }: any) => (
    <div data-testid="collapse" data-open={open}>
      {open ? children : null}
    </div>
  ),
}));

jest.mock("@shared/components/link", () => ({
  Link: ({ children, href, className }: any) => (
    <a data-testid="link" href={href} className={className}>
      {children}
    </a>
  ),
}));

jest.mock("@shared/components/material-icon", () => ({
  MaterialIcon: ({ name }: any) => (
    <span data-testid="material-icon">{name}</span>
  ),
}));

jest.mock("@shared/components/text", () => ({
  Text: ({ children, className }: any) => (
    <span className={className}>{children}</span>
  ),
}));

jest.mock("@shared/contentful/blocks/button", () => ({
  Button: ({ children, onClick, buttonClassName }: any) => (
    <button
      data-testid="tab-button"
      onClick={onClick}
      className={buttonClassName}
    >
      {children}
    </button>
  ),
}));

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

describe("DynamicTabs", () => {
  const defaultProps = {
    tabs: {
      items: [
        {
          tabName: "Tab 1",
          anchorId: "tab-1",
          tabContent: <div>Content 1</div>,
        },
        {
          tabName: "Tab 2",
          anchorId: "tab-2",
          tabContent: <div>Content 2</div>,
        },
        {
          tabName: "Tab 3",
          anchorId: "tab-3",
          tabContent: <div>Content 3</div>,
        },
      ],
    },
  };

  beforeEach(() => {
    jest.clearAllMocks();
    window.location.hash = "";
  });

  describe("Rendering", () => {
    it("renders all tab buttons", () => {
      render(<DynamicTabs {...defaultProps} />);
      expect(screen.getAllByText("Tab 1").length).toBeGreaterThan(0);
      expect(screen.getAllByText("Tab 2").length).toBeGreaterThan(0);
      expect(screen.getAllByText("Tab 3").length).toBeGreaterThan(0);
    });

    it("renders tab content", () => {
      render(<DynamicTabs {...defaultProps} />);
      expect(screen.getAllByText("Content 1").length).toBeGreaterThan(0);
    });

    it("renders title when provided", () => {
      render(<DynamicTabs {...defaultProps} title="My Tabs" />);
      expect(screen.getByText("My Tabs")).toBeInTheDocument();
    });

    it("renders subtitle when provided", () => {
      render(<DynamicTabs {...defaultProps} subTitle="A subtitle" />);
      expect(screen.getByText("A subtitle")).toBeInTheDocument();
    });

    it("does not render title section when no title or subtitle", () => {
      const { container } = render(<DynamicTabs {...defaultProps} />);
      expect(container.querySelector(".mb-8.mt-5")).not.toBeInTheDocument();
    });
  });

  describe("Tab switching", () => {
    it("switches tab content on click", () => {
      render(<DynamicTabs {...defaultProps} />);
      const tabButtons = screen.getAllByTestId("tab-button");
      // Find a Tab 2 button and click it
      const tab2Buttons = tabButtons.filter(btn => btn.textContent === "Tab 2");
      fireEvent.click(tab2Buttons[0]);
      // After clicking Tab 2, the motion-div for tab 2 should show opacity 1
      const motionDivs = screen.getAllByTestId("motion-div");
      expect(motionDivs.length).toBeGreaterThan(0);
    });

    it("first tab is active by default", () => {
      render(<DynamicTabs {...defaultProps} />);
      const tabButtons = screen.getAllByTestId("tab-button");
      const firstTabBtn = tabButtons.find(btn => btn.textContent === "Tab 1");
      expect(firstTabBtn?.className).toContain("border-b-2");
    });
  });

  describe("Navigation type", () => {
    it("renders tab view on desktop when navigationType is true", () => {
      const { container } = render(
        <DynamicTabs {...defaultProps} navigationType={true} />
      );
      // Desktop view should have the overflow-x-auto div in "hidden md:block"
      const desktopBlock = container.querySelector(".hidden.md\\:block");
      expect(desktopBlock).toBeInTheDocument();
    });

    it("renders sidebar view on desktop when navigationType is false", () => {
      const { container } = render(
        <DynamicTabs {...defaultProps} navigationType={false} />
      );
      const desktopBlock = container.querySelector(".hidden.md\\:block");
      expect(desktopBlock).toBeInTheDocument();
    });
  });

  describe("Mobile view", () => {
    it("renders tab view on mobile when mobileSidebarTabType is true", () => {
      const { container } = render(
        <DynamicTabs {...defaultProps} mobileSidebarTabType={true} />
      );
      const mobileBlock = container.querySelector(".md\\:hidden");
      expect(mobileBlock).toBeInTheDocument();
    });

    it("renders accordion view on mobile when mobileSidebarTabType is false", () => {
      render(<DynamicTabs {...defaultProps} mobileSidebarTabType={false} />);
      // Accordion uses Collapse component
      const collapses = screen.getAllByTestId("collapse");
      expect(collapses.length).toBeGreaterThan(0);
    });

    it("clicks accordion button to switch tabs", () => {
      window.location.hash = "#tab-1";
      const { container } = render(
        <DynamicTabs {...defaultProps} mobileSidebarTabType={false} />
      );
      // Accordion buttons are inside the mobile container (.md\:hidden)
      const mobileContainer = container.querySelector(".md\\:hidden");
      const accordionButtons = mobileContainer!.querySelectorAll(
        "[data-testid='tab-button']"
      );
      // Click the second accordion button (Tab 2)
      fireEvent.click(accordionButtons[1]);
      expect(window.location.hash).toBe("#tab-2");
    });
  });

  describe("Sidebar view", () => {
    it("clicks sidebar button to switch tabs", () => {
      window.location.hash = "#tab-1";
      const { container } = render(
        <DynamicTabs {...defaultProps} navigationType={false} />
      );
      // Sidebar buttons are inside the desktop container (.hidden.md\:block)
      const desktopContainer = container.querySelector(".hidden.md\\:block");
      const sidebarButtons = desktopContainer!.querySelectorAll(
        "[data-testid='tab-button']"
      );
      // Click the third sidebar button (Tab 3)
      fireEvent.click(sidebarButtons[2]);
      expect(window.location.hash).toBe("#tab-3");
    });
  });

  describe("Hash navigation", () => {
    it("sets tab based on URL hash", () => {
      window.location.hash = "#tab-2";
      render(<DynamicTabs {...defaultProps} />);
      // After useEffect runs, tab 2 should be active
      const tabButtons = screen.getAllByTestId("tab-button");
      const tab2Btns = tabButtons.filter(btn => btn.textContent === "Tab 2");
      // At least one Tab 2 button should have the active style
      const hasActiveTab2 = tab2Btns.some(btn =>
        btn.className.includes("border-b-2")
      );
      expect(hasActiveTab2).toBe(true);
    });

    it("updates hash on tab click when fragment exists", () => {
      window.location.hash = "#tab-1";
      render(<DynamicTabs {...defaultProps} />);
      const tabButtons = screen.getAllByTestId("tab-button");
      const tab2Btns = tabButtons.filter(btn => btn.textContent === "Tab 2");
      fireEvent.click(tab2Btns[0]);
      expect(window.location.hash).toBe("#tab-2");
    });

    it("listens to hashchange events", () => {
      render(<DynamicTabs {...defaultProps} />);
      act(() => {
        window.location.hash = "#tab-3";
        window.dispatchEvent(new HashChangeEvent("hashchange"));
      });
      const tabButtons = screen.getAllByTestId("tab-button");
      const tab3Btns = tabButtons.filter(btn => btn.textContent === "Tab 3");
      const hasActiveTab3 = tab3Btns.some(btn =>
        btn.className.includes("border-b-2")
      );
      expect(hasActiveTab3).toBe(true);
    });
  });

  describe("Empty state", () => {
    it("renders without tabs", () => {
      const { container } = render(<DynamicTabs />);
      expect(container.firstChild).toBeInTheDocument();
    });

    it("renders without tabsContent", () => {
      render(<DynamicTabs tabs={defaultProps.tabs} />);
      expect(screen.getAllByTestId("tab-button").length).toBeGreaterThan(0);
    });
  });

  describe("Ordered list mode", () => {
    const orderedProps = {
      dynamic: true,
      isOrderedList: true,
      tabs: {
        items: [
          {
            tabName: "Group A",
            anchorId: "tab-0",
            tabContent: [
              <span key="a1">Item A1</span>,
              <span key="a2">Item A2</span>,
            ],
          },
          {
            tabName: "Group B",
            anchorId: "tab-1",
            tabContent: [<span key="b1">Item B1</span>],
          },
        ],
      },
    };

    it("renders ordered tab names from the tabs prop", () => {
      render(<DynamicTabs {...orderedProps} />);
      expect(screen.getAllByText("Group A").length).toBeGreaterThan(0);
      expect(screen.getAllByText("Group B").length).toBeGreaterThan(0);
    });

    it("renders each tab's tabContent children", () => {
      render(<DynamicTabs {...orderedProps} />);
      expect(screen.getAllByText("Item A1").length).toBeGreaterThan(0);
      expect(screen.getAllByText("Item A2").length).toBeGreaterThan(0);
    });

    it("updates hash when an ordered tab is clicked", () => {
      window.location.hash = "#tab-0";
      render(<DynamicTabs {...orderedProps} />);
      const tabButtons = screen.getAllByTestId("tab-button");
      const groupB = tabButtons.filter(btn => btn.textContent === "Group B");
      fireEvent.click(groupB[0]);
      expect(window.location.hash).toBe("#tab-1");
    });

    it("renders sidebar layout when navigationType is false", () => {
      const { container } = render(
        <DynamicTabs {...orderedProps} navigationType={false} />
      );
      expect(container.querySelector(".hidden.lg\\:block")).toBeInTheDocument();
      expect(screen.getAllByText("Group A").length).toBeGreaterThan(0);
    });

    it("renders accordion layout when mobileSidebarTabType is false", () => {
      const { container } = render(
        <DynamicTabs {...orderedProps} mobileSidebarTabType={false} />
      );
      expect(container.querySelector(".lg\\:hidden")).toBeInTheDocument();
      expect(screen.getAllByText("Item B1").length).toBeGreaterThan(0);
    });
  });
});
