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

import { CarouselHero } from "../CarouselHero";
import { CarouselHeroItem } from "../CarouselHeroItem";

describe("rendering CarouselHero", () => {
  describe("initial state", () => {
    it("has default class carousel-hero", () => {
      const { getByTestId } = render(<CarouselHero data-testid="test-id" />);
      expect(getByTestId("test-id")).toHaveClass("carousel-hero");
    });

    it("has data-carousel-hero attribute", () => {
      const { container } = render(<CarouselHero />);
      expect(container.querySelector(".carousel-hero")).toHaveAttribute(
        "data-carousel-hero",
      );
    });

    it("has default class carousel-hero__viewport-wrapper", () => {
      const { container } = render(<CarouselHero />);
      expect(
        container.getElementsByClassName("carousel-hero__viewport-wrapper")
          .length,
      ).toBe(1);
    });

    it("has default class carousel-hero__viewport", () => {
      const { container } = render(<CarouselHero />);
      expect(
        container.getElementsByClassName("carousel-hero__viewport").length,
      ).toBe(1);
    });

    it("has default class carousel-hero__track", () => {
      const { container } = render(<CarouselHero />);
      expect(
        container.getElementsByClassName("carousel-hero__track").length,
      ).toBe(1);
    });

    it("has container with d-flex class for controls", () => {
      const { container } = render(<CarouselHero />);
      expect(container.querySelector(".container.d-flex")).toBeInTheDocument();
    });

    it("has default class carousel-hero__navigation", () => {
      const { container } = render(<CarouselHero />);
      expect(
        container.getElementsByClassName("carousel-hero__navigation").length,
      ).toBe(1);
    });

    it("has default class carousel-hero__pagination", () => {
      const { container } = render(<CarouselHero />);
      expect(
        container.getElementsByClassName("carousel-hero__pagination").length,
      ).toBe(1);
    });

    it("renders navigation controls (prev/next)", () => {
      const { container } = render(<CarouselHero />);
      expect(
        container.getElementsByClassName("carousel-hero__prev").length,
      ).toBe(1);
      expect(
        container.getElementsByClassName("carousel-hero__next").length,
      ).toBe(1);
    });

    it("navigation controls have proper ARIA labels", () => {
      const { container } = render(<CarouselHero />);

      const prevButton = container.querySelector(".carousel-hero__prev");
      const nextButton = container.querySelector(".carousel-hero__next");

      expect(prevButton).toHaveAttribute("aria-label", "Predchádzajúci snímok");
      expect(nextButton).toHaveAttribute("aria-label", "Nasledujúci snímok");
    });

    it("play/pause button has proper ARIA label when displayed", () => {
      const { container } = render(
        <CarouselHero enableAutoplay interval={3000} />,
      );

      const playPauseButton = container.querySelector(
        ".carousel-hero__play-pause",
      );
      expect(playPauseButton).toHaveAttribute(
        "aria-label",
        "Pozastaviť/Spustiť automatické prehrávanie",
      );
    });
  });

  describe("passed props", () => {
    const tabs = [{ label: "Tab 1" }, { label: "Tab 2" }, { label: "Tab 3" }];

    const children = (
      <>
        <CarouselHeroItem key="slide-1" image="https://placehold.co/720x560">
          <h2>Test Title 1</h2>
          <p>Test content 1</p>
        </CarouselHeroItem>
        <CarouselHeroItem key="slide-2" image="https://placehold.co/720x560">
          <h2>Test Title 2</h2>
          <p>Test content 2</p>
        </CarouselHeroItem>
      </>
    );

    it("renders children slides", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);
      const slides = container.getElementsByClassName("carousel-hero__slide");
      expect(slides.length).toBe(2);
      expect(slides[0]).toHaveTextContent("Test Title 1");
      expect(slides[1]).toHaveTextContent("Test Title 2");
    });

    it("has additional class when className is set", () => {
      const { getByTestId } = render(
        <CarouselHero data-testid="test-id" className="test-class" />,
      );
      expect(getByTestId("test-id")).toHaveClass("carousel-hero");
      expect(getByTestId("test-id")).toHaveClass("test-class");
    });

    it("does not have is-light or is-dark class by default", () => {
      const { getByTestId } = render(<CarouselHero data-testid="test-id" />);
      expect(getByTestId("test-id")).not.toHaveClass("is-light");
      expect(getByTestId("test-id")).not.toHaveClass("is-dark");
    });

    it("renders tabs when tabs prop is provided", () => {
      const { container } = render(
        <CarouselHero tabs={tabs}>{children}</CarouselHero>,
      );

      const tabsContainer = container.querySelector(".carousel-hero__tabs");
      expect(tabsContainer).toBeInTheDocument();
      expect(tabsContainer).toHaveAttribute("role", "tablist");

      const tabButtons = container.querySelectorAll(".carousel-hero__tab");
      expect(tabButtons.length).toBe(3);
      expect(tabButtons[0]).toHaveTextContent("Tab 1");
      expect(tabButtons[1]).toHaveTextContent("Tab 2");
      expect(tabButtons[2]).toHaveTextContent("Tab 3");
    });

    it("does not render tabs when tabs prop is empty", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);

      const tabsContainer = container.querySelector(".carousel-hero__tabs");
      expect(tabsContainer).not.toBeInTheDocument();
    });

    it("sets proper ARIA attributes on tabs", () => {
      const { container } = render(
        <CarouselHero id="test-carousel" tabs={tabs}>
          {children}
        </CarouselHero>,
      );

      const tabButtons = container.querySelectorAll(".carousel-hero__tab");

      // First tab should be active
      expect(tabButtons[0]).toHaveAttribute("role", "tab");
      expect(tabButtons[0]).toHaveAttribute("id", "test-carousel-tab-0");
      expect(tabButtons[0]).toHaveAttribute(
        "aria-controls",
        "test-carousel-panel-0",
      );
      expect(tabButtons[0]).toHaveAttribute("aria-selected", "true");
      expect(tabButtons[0]).toHaveAttribute("tabIndex", "0");

      // Other tabs should not be active
      expect(tabButtons[1]).toHaveAttribute("aria-selected", "false");
      expect(tabButtons[1]).toHaveAttribute("tabIndex", "-1");
      expect(tabButtons[2]).toHaveAttribute("aria-selected", "false");
      expect(tabButtons[2]).toHaveAttribute("tabIndex", "-1");
    });

    it("links tabs to corresponding tabpanels", () => {
      const { container } = render(
        <CarouselHero id="test-carousel" tabs={tabs}>
          {children}
        </CarouselHero>,
      );

      const slides = container.getElementsByClassName("carousel-hero__slide");

      expect(slides[0]).toHaveAttribute("role", "tabpanel");
      expect(slides[0]).toHaveAttribute("id", "test-carousel-panel-0");
      expect(slides[0]).toHaveAttribute(
        "aria-labelledby",
        "test-carousel-tab-0",
      );
      expect(slides[1]).toHaveAttribute("role", "tabpanel");
      expect(slides[1]).toHaveAttribute("id", "test-carousel-panel-1");
      expect(slides[1]).toHaveAttribute(
        "aria-labelledby",
        "test-carousel-tab-1",
      );
    });

    it("shows play/pause button when autoplay is enabled and interval is provided", () => {
      const { container } = render(
        <CarouselHero enableAutoplay interval={3000}>
          {children}
        </CarouselHero>,
      );

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(1);
    });

    it("does not show play/pause button when autoplay is not enabled", () => {
      const { container } = render(
        <CarouselHero interval={3000}>{children}</CarouselHero>,
      );

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(0);
    });

    it("does not show play/pause button when interval is not provided", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(0);
    });

    it("does not show play/pause button when interval is 0", () => {
      const { container } = render(
        <CarouselHero interval={0}>{children}</CarouselHero>,
      );

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(0);
    });

    it("sets data-interval attribute when autoplay is enabled and interval is provided", () => {
      const { container } = render(
        <CarouselHero enableAutoplay interval={5000}>
          {children}
        </CarouselHero>,
      );

      const carousel = container.querySelector(".carousel-hero");
      expect(carousel).toHaveAttribute("data-interval", "5000");
    });

    it("does not set data-interval attribute when autoplay is not enabled", () => {
      const { container } = render(
        <CarouselHero interval={5000}>{children}</CarouselHero>,
      );

      const carousel = container.querySelector(".carousel-hero");
      expect(carousel).not.toHaveAttribute("data-interval");
    });

    it("does not set data-interval attribute when interval is not provided", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);

      const carousel = container.querySelector(".carousel-hero");
      expect(carousel).not.toHaveAttribute("data-interval");
    });
  });

  describe("swiperOptions prop", () => {
    const children = (
      <CarouselHeroItem key="slide-1" image="https://placehold.co/720x560">
        <h2>Test Title</h2>
        <p>Test content</p>
      </CarouselHeroItem>
    );

    it("sets data-swiper-options attribute when swiperOptions prop is provided", () => {
      const swiperOptions = { speed: 500, loop: true };
      const { container } = render(
        <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
      );

      const carousel = container.querySelector(".carousel-hero");
      expect(carousel.getAttribute("data-swiper-options")).toBe(
        JSON.stringify(swiperOptions),
      );
    });

    it("does not set data-swiper-options attribute when swiperOptions prop is not provided", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);

      const carousel = container.querySelector(".carousel-hero");
      expect(carousel.hasAttribute("data-swiper-options")).toBe(false);
    });

    it("shows play/pause button when autoplay is enabled and swiperOptions has autoplay with delay >= 1000ms", () => {
      const swiperOptions = {
        autoplay: {
          delay: 3000,
          disableOnInteraction: false,
        },
      };
      const { container } = render(
        <CarouselHero enableAutoplay swiperOptions={swiperOptions}>
          {children}
        </CarouselHero>,
      );

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(1);
    });

    it("does not show play/pause button when autoplay is not enabled, even if swiperOptions includes autoplay", () => {
      const swiperOptions = {
        autoplay: {
          delay: 3000,
          disableOnInteraction: false,
        },
      };
      const { container } = render(
        <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
      );

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(0);

      const carousel = container.querySelector(".carousel-hero");
      expect(carousel).not.toHaveAttribute(
        "data-swiper-options",
        JSON.stringify(swiperOptions),
      );
    });

    it("does not show play/pause button when swiperOptions autoplay delay < 1000ms", () => {
      const swiperOptions = {
        autoplay: {
          delay: 500,
        },
      };
      const { container } = render(
        <CarouselHero enableAutoplay swiperOptions={swiperOptions}>
          {children}
        </CarouselHero>,
      );

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(0);
    });

    it("does not show play/pause button when autoplay is boolean true", () => {
      const swiperOptions = {
        autoplay: true,
      };
      const { container } = render(
        <CarouselHero enableAutoplay swiperOptions={swiperOptions}>
          {children}
        </CarouselHero>,
      );

      expect(
        container.getElementsByClassName("carousel-hero__play-pause").length,
      ).toBe(0);
    });
    it("removes autoplay from forwarded swiperOptions until autoplay is enabled", () => {
      const swiperOptions = {
        autoplay: {
          delay: 3000,
        },
        speed: 500,
      };
      const { container } = render(
        <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
      );

      const carousel = container.querySelector(".carousel-hero");
      expect(carousel.getAttribute("data-swiper-options")).toBe(
        JSON.stringify({ speed: 500 }),
      );
    });
  });

  describe("Swiper integration", () => {
    const children = (
      <>
        <CarouselHeroItem key="slide-1" image="https://placehold.co/720x560">
          <h2>Test Title 1</h2>
          <p>Test content 1</p>
        </CarouselHeroItem>
        <CarouselHeroItem key="slide-2" image="https://placehold.co/720x560">
          <h2>Test Title 2</h2>
          <p>Test content 2</p>
        </CarouselHeroItem>
      </>
    );

    it("track element uses carousel-hero__track class which maps to swiper-wrapper", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);
      expect(
        container.querySelector(".carousel-hero__track"),
      ).toBeInTheDocument();
    });

    it("slide elements use carousel-hero__slide class which maps to swiper-slide", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);
      const slides = container.getElementsByClassName("carousel-hero__slide");
      expect(slides.length).toBe(2);
    });

    it("viewport element uses carousel-hero__viewport class which maps to swiper-container", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);
      expect(
        container.querySelector(".carousel-hero__viewport"),
      ).toBeInTheDocument();
    });

    it("pagination element uses carousel-hero__pagination class which maps to swiper-pagination", () => {
      const { container } = render(<CarouselHero>{children}</CarouselHero>);
      expect(
        container.querySelector(".carousel-hero__pagination"),
      ).toBeInTheDocument();
    });
  });
});
