import "@testing-library/jest-dom";

import React from "react";
import { Carousel } from "./index";
import { CarouselProps } from "./types";

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

// Mock helper components
jest.mock("./helper", () => ({
  ProductCardCarousel: ({ fields }: any) => (
    <div data-testid="product-card-carousel">{fields?.title}</div>
  ),
  TestimonialCarousel: ({ fields }: any) => (
    <div data-testid="testimonial-carousel">{fields?.title}</div>
  ),
  TabSwitch: ({ tabs, activeTab, onChange }: any) => (
    <div data-testid="tab-switch">
      {tabs.map((tab: string) => (
        <button
          key={tab}
          data-testid={`tab-${tab}`}
          onClick={() => onChange(tab)}
          className={activeTab === tab ? "active" : ""}
        >
          {tab}
        </button>
      ))}
    </div>
  ),
}));

jest.mock("@shared/components/text", () => ({
  Text: ({ children, as, ...props }: any) => {
    const Tag = as || "span";
    return <Tag {...props}>{children}</Tag>;
  },
}));

describe("Carousel", () => {
  const baseFields = {
    __typename: "ComponentCarousel" as const,
    sys: { id: "carousel-1" },
    title: "Test Carousel",
    subTitle: "A subtitle",
    items: { items: [] },
  };

  const defaultProps: CarouselProps = {
    fields: baseFields,
    hasTestimonialCards: false,
    hasProductCards: false,
    disclaimerText: null,
    backgroundColor: "bg-white",
    activeTab: "Internet Only",
    setActiveTab: jest.fn(),
    tabs: ["Business Ready", "Internet Only"],
    showSwitch: false,
  };

  it("renders the carousel container", () => {
    const { container } = render(<Carousel {...defaultProps} />);
    expect(container.firstChild).toBeInTheDocument();
  });

  it("renders the title", () => {
    render(<Carousel {...defaultProps} />);
    expect(screen.getByText("Test Carousel")).toBeInTheDocument();
  });

  it("renders title as h2", () => {
    render(<Carousel {...defaultProps} />);
    const title = screen.getByText("Test Carousel");
    expect(title.tagName).toBe("H2");
  });

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

  it("renders subtitle as h3", () => {
    render(<Carousel {...defaultProps} />);
    const subtitle = screen.getByText("A subtitle");
    expect(subtitle.tagName).toBe("H3");
  });

  it("does not render subtitle when not provided", () => {
    const fields = { ...baseFields, subTitle: undefined };
    render(<Carousel {...defaultProps} fields={fields} />);
    expect(screen.queryByText("A subtitle")).not.toBeInTheDocument();
  });

  it("does not render subtitle when it is null", () => {
    const fields = { ...baseFields, subTitle: null as any };
    render(<Carousel {...defaultProps} fields={fields} />);
    const h3Elements = document.querySelectorAll("h3");
    expect(h3Elements).toHaveLength(0);
  });

  it("does not render subtitle when it is empty string", () => {
    const fields = { ...baseFields, subTitle: "" };
    render(<Carousel {...defaultProps} fields={fields} />);
    // Empty string is falsy so subtitle block should not render
    const h3Elements = document.querySelectorAll("h3");
    expect(h3Elements).toHaveLength(0);
  });

  it("renders with undefined title", () => {
    const fields = { ...baseFields, title: undefined };
    render(<Carousel {...defaultProps} fields={fields} />);
    // Should not crash, h2 renders but empty
    const h2 = document.querySelector("h2");
    expect(h2).toBeInTheDocument();
  });

  it("uses default showSwitch and testimonialAutoScroll when not provided", () => {
    const propsWithoutDefaults = { ...defaultProps } as any;
    delete propsWithoutDefaults.showSwitch;
    delete propsWithoutDefaults.testimonialAutoScroll;
    render(<Carousel {...propsWithoutDefaults} hasTestimonialCards={true} />);
    // showSwitch defaults to false so no product carousel shown
    expect(
      screen.queryByTestId("product-card-carousel")
    ).not.toBeInTheDocument();
    // testimonialAutoScroll defaults to true, testimonial renders
    expect(screen.getByTestId("testimonial-carousel")).toBeInTheDocument();
  });

  it("renders disclaimer text when provided", () => {
    render(<Carousel {...defaultProps} disclaimerText="Terms apply" />);
    expect(screen.getByText("Terms apply")).toBeInTheDocument();
  });

  it("does not render disclaimer when null", () => {
    const { container } = render(<Carousel {...defaultProps} />);
    expect(container.querySelector(".footnote")).not.toBeInTheDocument();
  });

  it("applies backgroundColor class", () => {
    const { container } = render(
      <Carousel {...defaultProps} backgroundColor="bg-blue-500" />
    );
    expect(container.firstChild).toHaveClass("bg-blue-500");
  });

  describe("product cards", () => {
    it("renders ProductCardCarousel when hasProductCards is true and showSwitch is true", () => {
      render(
        <Carousel {...defaultProps} hasProductCards={true} showSwitch={true} />
      );
      expect(screen.getByTestId("product-card-carousel")).toBeInTheDocument();
    });

    it("renders ProductCardCarousel when hasProductCards is true even if showSwitch is false", () => {
      render(
        <Carousel {...defaultProps} hasProductCards={true} showSwitch={false} />
      );
      expect(screen.getByTestId("product-card-carousel")).toBeInTheDocument();
      expect(screen.queryByTestId("tab-switch")).not.toBeInTheDocument();
    });

    it("renders TabSwitch when showSwitch and hasProductCards with multiple tabs", () => {
      render(
        <Carousel
          {...defaultProps}
          hasProductCards={true}
          showSwitch={true}
          tabs={["Tab A", "Tab B"]}
        />
      );
      expect(screen.getByTestId("tab-switch")).toBeInTheDocument();
    });

    it("does not render TabSwitch when only one tab", () => {
      render(
        <Carousel
          {...defaultProps}
          hasProductCards={true}
          showSwitch={true}
          tabs={["Only Tab"]}
        />
      );
      expect(screen.queryByTestId("tab-switch")).not.toBeInTheDocument();
    });

    it("calls setActiveTab when tab is clicked", () => {
      const setActiveTab = jest.fn();
      render(
        <Carousel
          {...defaultProps}
          hasProductCards={true}
          showSwitch={true}
          setActiveTab={setActiveTab}
          tabs={["Tab A", "Tab B"]}
        />
      );
      fireEvent.click(screen.getByTestId("tab-Tab A"));
      expect(setActiveTab).toHaveBeenCalledWith("Tab A");
    });
  });

  describe("testimonial cards", () => {
    it("renders TestimonialCarousel when hasTestimonialCards is true", () => {
      render(<Carousel {...defaultProps} hasTestimonialCards={true} />);
      expect(screen.getByTestId("testimonial-carousel")).toBeInTheDocument();
    });

    it("does not render TestimonialCarousel when hasTestimonialCards is false", () => {
      render(<Carousel {...defaultProps} hasTestimonialCards={false} />);
      expect(
        screen.queryByTestId("testimonial-carousel")
      ).not.toBeInTheDocument();
    });

    it("passes testimonialAutoScroll prop correctly", () => {
      render(
        <Carousel
          {...defaultProps}
          hasTestimonialCards={true}
          testimonialAutoScroll={false}
        />
      );
      expect(screen.getByTestId("testimonial-carousel")).toBeInTheDocument();
    });
  });

  describe("layout classes", () => {
    it("applies product card base class when hasProductCards", () => {
      const { container } = render(
        <Carousel {...defaultProps} hasProductCards={true} showSwitch={true} />
      );
      expect(container.firstChild).toHaveClass("px-3");
      expect(container.firstChild).toHaveClass("py-9");
    });

    it("applies testimonial base class when hasTestimonialCards", () => {
      const { container } = render(
        <Carousel {...defaultProps} hasTestimonialCards={true} />
      );
      expect(container.firstChild).toHaveClass("px-3");
      expect(container.firstChild).toHaveClass("py-12");
    });

    it("applies no base class when neither card type", () => {
      const { container } = render(<Carousel {...defaultProps} />);
      expect(container.firstChild).toHaveClass("mx-auto");
      expect(container.firstChild).toHaveClass("overflow-hidden");
    });

    it("applies overflow-hidden to root", () => {
      const { container } = render(<Carousel {...defaultProps} />);
      expect(container.firstChild).toHaveClass("overflow-hidden");
    });

    it("applies product class without testimonial when only hasProductCards", () => {
      const { container } = render(
        <Carousel
          {...defaultProps}
          hasProductCards={true}
          hasTestimonialCards={false}
          showSwitch={true}
        />
      );
      expect(container.firstChild).toHaveClass("py-9");
    });

    it("renders both product and testimonial when both flags are true", () => {
      render(
        <Carousel
          {...defaultProps}
          hasProductCards={true}
          hasTestimonialCards={true}
          showSwitch={true}
        />
      );
      expect(screen.getByTestId("product-card-carousel")).toBeInTheDocument();
      expect(screen.getByTestId("testimonial-carousel")).toBeInTheDocument();
    });

    it("renders product carousel and hides tab switch when showSwitch is false with hasProductCards", () => {
      render(
        <Carousel
          {...defaultProps}
          hasProductCards={true}
          showSwitch={false}
          hasTestimonialCards={false}
        />
      );
      expect(screen.getByTestId("product-card-carousel")).toBeInTheDocument();
      expect(screen.queryByTestId("tab-switch")).not.toBeInTheDocument();
    });

    it("renders with empty tabs array and no TabSwitch", () => {
      render(
        <Carousel
          {...defaultProps}
          hasProductCards={true}
          showSwitch={true}
          tabs={[]}
        />
      );
      expect(screen.queryByTestId("tab-switch")).not.toBeInTheDocument();
    });
  });
});
