/**
 * @vitest-environment jsdom
 */

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

import { PromoBanner } from "../";

describe("PromoBanner", () => {
  describe("rendering", () => {
    describe("initial state", () => {
      it("renders with default props", () => {
        render(<PromoBanner />);
        const banner = document.querySelector(".promo-banner");
        expect(banner).toBeInTheDocument();
      });

      it("has default CSS class", () => {
        render(<PromoBanner />);
        const banner = document.querySelector(".promo-banner");
        expect(banner).toHaveClass("promo-banner");
        const grid = banner.querySelector(".grid");
        expect(grid).toBeInTheDocument();
      });

      it("renders as Grid component", () => {
        const { container } = render(<PromoBanner />);
        const banner = container.querySelector(".promo-banner");
        const grid = banner.querySelector(".grid");
        expect(grid).toBeInTheDocument();
        expect(grid).toHaveClass("grid");
      });
    });

    describe("content", () => {
      it("renders children content", () => {
        render(
          <PromoBanner>
            <h2>Test Title</h2>
            <p>Test description</p>
          </PromoBanner>,
        );

        expect(screen.getByRole("heading", { level: 2 })).toHaveTextContent(
          "Test Title",
        );
        expect(screen.getByText("Test description")).toBeInTheDocument();
      });

      it("renders text children", () => {
        render(<PromoBanner>Simple text content</PromoBanner>);
        expect(screen.getByText("Simple text content")).toBeInTheDocument();
      });

      it("renders complex JSX children", () => {
        render(
          <PromoBanner>
            <div data-testid="complex-content">
              <h1>Complex Title</h1>
              <p>
                Complex description with <strong>bold text</strong>
              </p>
              <button type="button">Action Button</button>
            </div>
          </PromoBanner>,
        );

        expect(screen.getByTestId("complex-content")).toBeInTheDocument();
        expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent(
          "Complex Title",
        );
        expect(screen.getByRole("button")).toHaveTextContent("Action Button");
      });

      it("renders multiple children", () => {
        render(
          <PromoBanner>
            <h2>Title</h2>
            <p>Description</p>
            <button type="button">Button</button>
          </PromoBanner>,
        );

        expect(screen.getByRole("heading")).toBeInTheDocument();
        expect(screen.getByText("Description")).toBeInTheDocument();
        expect(screen.getByRole("button")).toBeInTheDocument();
      });
    });

    describe("prop variations", () => {
      describe("className", () => {
        it("applies custom className", () => {
          render(<PromoBanner className="custom-class" />);
          const banner = document.querySelector(".promo-banner");
          expect(banner).toHaveClass("custom-class");
        });

        it("merges custom className with default", () => {
          render(<PromoBanner className="custom-class" />);
          const banner = document.querySelector(".promo-banner");
          expect(banner).toHaveClass("promo-banner", "custom-class");
        });
      });

      describe("itemClassName", () => {
        it("applies custom itemClassName to content column", () => {
          render(
            <PromoBanner itemClassName="custom-item-class">
              Content
            </PromoBanner>,
          );
          const item = document.querySelector(".promo-banner__item");
          expect(item).toHaveClass("custom-item-class");
        });

        it("merges itemClassName with default item classes", () => {
          render(
            <PromoBanner itemClassName="custom-item-class">
              Content
            </PromoBanner>,
          );
          const item = document.querySelector(".promo-banner__item");
          expect(item).toHaveClass("promo-banner__item", "custom-item-class");
        });
      });

      describe("flushTopSmDown", () => {
        it("applies explicit top flush modifier class", () => {
          render(<PromoBanner flushTopSmDown>Content</PromoBanner>);
          const banner = document.querySelector(".promo-banner");
          expect(banner).toHaveClass("promo-banner--flush-top-sm-down");
        });

        it("does not apply explicit top flush modifier class when disabled", () => {
          render(<PromoBanner>Content</PromoBanner>);
          const banner = document.querySelector(".promo-banner");
          expect(banner).not.toHaveClass("promo-banner--flush-top-sm-down");
        });
      });

      describe("flushBottomSmDown", () => {
        it("applies explicit bottom flush modifier class", () => {
          render(<PromoBanner flushBottomSmDown>Content</PromoBanner>);
          const banner = document.querySelector(".promo-banner");
          expect(banner).toHaveClass("promo-banner--flush-bottom-sm-down");
        });

        it("does not apply explicit bottom flush modifier class when disabled", () => {
          render(<PromoBanner>Content</PromoBanner>);
          const banner = document.querySelector(".promo-banner");
          expect(banner).not.toHaveClass("promo-banner--flush-bottom-sm-down");
        });
      });

      describe("bleedImageSmDown", () => {
        it("applies image bleed modifier class", () => {
          render(
            <PromoBanner image="test.jpg" bleedImageSmDown>
              Content
            </PromoBanner>,
          );
          const image = document.querySelector(".promo-banner__image");
          expect(image).toHaveClass("promo-banner__image--bleed-sm-down");
        });

        it("does not apply image bleed modifier class when disabled", () => {
          render(<PromoBanner image="test.jpg">Content</PromoBanner>);
          const image = document.querySelector(".promo-banner__image");
          expect(image).not.toHaveClass("promo-banner__image--bleed-sm-down");
        });
      });
    });

    describe("variant", () => {
      describe("default (horizontal) variant", () => {
        it("uses correct column sizes without image", () => {
          render(<PromoBanner>Content</PromoBanner>);
          const contentCol = document
            .querySelector(".promo-banner__item")
            .closest(".grid__col");
          expect(contentCol).toHaveClass("grid__col");
        });

        it("uses correct column sizes with image", () => {
          render(<PromoBanner image="test.jpg">Content</PromoBanner>);
          const contentCol = document
            .querySelector(".promo-banner__item")
            .closest(".grid__col");
          const imageCol = document
            .querySelector(".promo-banner__image")
            .closest(".grid__col");
          expect(contentCol).toHaveClass("grid__col");
          expect(imageCol).toHaveClass("grid__col");
        });

        it("does not apply vertical-specific classes", () => {
          render(<PromoBanner>Content</PromoBanner>);
          const item = document.querySelector(".promo-banner__item");
          expect(item).not.toHaveClass(
            "align-items-center",
            "align-center",
            "align-self-center",
          );
        });
      });

      describe("vertical variant", () => {
        it("applies vertical modifier class to root", () => {
          render(<PromoBanner variant="vertical">Content</PromoBanner>);
          const banner = document.querySelector(".promo-banner");
          expect(banner).toHaveClass("promo-banner--vertical");
        });

        it("applies vertical variant column layout", () => {
          render(<PromoBanner variant="vertical">Content</PromoBanner>);
          const contentCol = document
            .querySelector(".promo-banner__item")
            .closest(".grid__col");
          expect(contentCol).toHaveClass("grid__col");
        });

        it("applies vertical alignment classes", () => {
          render(<PromoBanner variant="vertical">Content</PromoBanner>);
          const item = document.querySelector(".promo-banner__item");
          expect(item).toHaveClass(
            "align-items-center",
            "align-center",
            "align-self-center",
          );
        });

        it("applies vertical image column layout", () => {
          render(
            <PromoBanner variant="vertical" image="test.jpg">
              Content
            </PromoBanner>,
          );
          const imageCol = document
            .querySelector(".promo-banner__image")
            .closest(".grid__col");
          expect(imageCol).toHaveClass("grid__col");
        });

        it("applies center alignment to image in vertical variant", () => {
          render(
            <PromoBanner variant="vertical" image="test.jpg">
              Content
            </PromoBanner>,
          );
          const imageElement = document.querySelector(".promo-banner__image");
          expect(imageElement).toHaveClass("align-center");
        });
      });

      describe("reverse variant", () => {
        it("applies reverse modifier class to root", () => {
          render(
            <PromoBanner variant="reverse" image="test.jpg">
              Content
            </PromoBanner>,
          );
          const banner = document.querySelector(".promo-banner");
          expect(banner).toHaveClass("promo-banner--reverse");
        });

        it("applies reverse variant column layout", () => {
          render(
            <PromoBanner variant="reverse" image="test.jpg">
              Content
            </PromoBanner>,
          );
          const contentCol = document
            .querySelector(".promo-banner__item")
            .closest(".grid__col");
          const imageCol = document
            .querySelector(".promo-banner__image")
            .closest(".grid__col");
          expect(contentCol).toHaveClass("grid__col");
          expect(imageCol).toHaveClass("grid__col");
        });

        it("renders image before content in DOM order", () => {
          render(
            <PromoBanner variant="reverse" image="test.jpg">
              Content
            </PromoBanner>,
          );
          const grid = document.querySelector(".grid");
          const children = Array.from(grid.children);
          const imageCol = document
            .querySelector(".promo-banner__image")
            .closest(".grid__col");
          const contentCol = document
            .querySelector(".promo-banner__item")
            .closest(".grid__col");

          expect(children.indexOf(imageCol)).toBeLessThan(
            children.indexOf(contentCol),
          );
        });

        it("does not apply vertical-specific classes", () => {
          render(
            <PromoBanner variant="reverse" image="test.jpg">
              Content
            </PromoBanner>,
          );
          const item = document.querySelector(".promo-banner__item");
          expect(item).not.toHaveClass(
            "align-items-center",
            "align-center",
            "align-self-center",
          );
        });
      });
    });

    describe("image", () => {
      it("does not render image when not provided", () => {
        render(<PromoBanner>Content only</PromoBanner>);
        const image = document.querySelector(".promo-banner__image");
        expect(image).not.toBeInTheDocument();
      });

      it("renders image when provided", () => {
        render(
          <PromoBanner image="https://example.com/test.jpg">
            Content
          </PromoBanner>,
        );
        const image = screen.getByRole("img");
        expect(image).toBeInTheDocument();
        expect(image).toHaveAttribute("src", "https://example.com/test.jpg");
      });

      it("renders image from object src when image object is provided", () => {
        render(
          <PromoBanner
            image={{ src: "https://example.com/test.jpg", srcSet: "test" }}
          >
            Content
          </PromoBanner>,
        );
        const image = screen.getByRole("img");
        expect(image).toHaveAttribute("src", "https://example.com/test.jpg");
      });

      it("passes srcSet to Image when image object is provided", () => {
        render(
          <PromoBanner
            image={{
              src: "https://example.com/test.jpg",
              srcSet:
                "https://example.com/test.jpg, https://example.com/test@2x.jpg 2x",
            }}
          >
            Content
          </PromoBanner>,
        );
        const image = screen.getByRole("img");
        expect(image).toHaveAttribute(
          "srcSet",
          "https://example.com/test.jpg, https://example.com/test@2x.jpg 2x",
        );
      });

      it("applies default alt text", () => {
        render(<PromoBanner image="test.jpg">Content</PromoBanner>);
        const image = screen.getByRole("img");
        expect(image).toHaveAttribute("alt", "Obrázok");
      });

      it("has default image classes", () => {
        render(<PromoBanner image="test.jpg">Content</PromoBanner>);
        const image = screen.getByRole("img");
        expect(image).toHaveClass("mb-none");
      });

      describe("imageClassName", () => {
        it("applies custom imageClassName", () => {
          render(
            <PromoBanner image="test.jpg" imageClassName="custom-image-class">
              Content
            </PromoBanner>,
          );
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).toHaveClass("custom-image-class");
        });

        it("merges imageClassName with default image classes", () => {
          render(
            <PromoBanner image="test.jpg" imageClassName="custom-image-class">
              Content
            </PromoBanner>,
          );
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).toHaveClass(
            "promo-banner__image",
            "custom-image-class",
          );
        });
      });

      describe("alignImage", () => {
        it("applies bottom alignment", () => {
          render(
            <PromoBanner image="test.jpg" alignImage="bottom">
              Content
            </PromoBanner>,
          );
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).toHaveClass("align-self-bottom");
        });

        it("applies top alignment", () => {
          render(
            <PromoBanner image="test.jpg" alignImage="top">
              Content
            </PromoBanner>,
          );
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).toHaveClass("align-self-top");
        });

        it("does not apply alignment class when not specified", () => {
          render(<PromoBanner image="test.jpg">Content</PromoBanner>);
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).not.toHaveClass("align-self-bottom");
          expect(imageContainer).not.toHaveClass("align-self-top");
        });
      });

      describe("bleedImage", () => {
        it("applies bleed class when bleedImage is true", () => {
          render(
            <PromoBanner image="test.jpg" bleedImage>
              Content
            </PromoBanner>,
          );
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).toHaveClass(
            "promo-banner__image--bleed-right",
          );
        });

        it("does not apply bleed class when bleedImage is false", () => {
          render(
            <PromoBanner image="test.jpg" bleedImage={false}>
              Content
            </PromoBanner>,
          );
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).not.toHaveClass(
            "promo-banner__image--bleed-right",
          );
        });

        it("does not apply bleed class when bleedImage is not specified", () => {
          render(<PromoBanner image="test.jpg">Content</PromoBanner>);
          const imageContainer = document.querySelector(".promo-banner__image");
          expect(imageContainer).not.toHaveClass(
            "promo-banner__image--bleed-right",
          );
        });
      });

      describe("imageFullWidth", () => {
        it("applies fullwidth class when imageFullWidth is true", () => {
          render(
            <PromoBanner image="test.jpg" imageFullWidth>
              Content
            </PromoBanner>,
          );
          const image = screen.getByRole("img");
          expect(image).toHaveClass("fullwidth");
        });

        it("does not apply fullwidth class when imageFullWidth is false", () => {
          render(
            <PromoBanner image="test.jpg" imageFullWidth={false}>
              Content
            </PromoBanner>,
          );
          const image = screen.getByRole("img");
          expect(image).not.toHaveClass("fullwidth");
        });

        it("does not apply fullwidth class when imageFullWidth is not specified", () => {
          render(<PromoBanner image="test.jpg">Content</PromoBanner>);
          const image = screen.getByRole("img");
          expect(image).not.toHaveClass("fullwidth");
        });
      });
    });

    describe("combined props", () => {
      it("handles all image-related props together", () => {
        render(
          <PromoBanner
            image="test.jpg"
            alignImage="top"
            bleedImage
            imageFullWidth
            imageClassName="custom-image"
          >
            Content
          </PromoBanner>,
        );

        const imageContainer = document.querySelector(".promo-banner__image");
        const image = screen.getByRole("img");

        expect(imageContainer).toHaveClass(
          "promo-banner__image",
          "promo-banner__image--bleed-right",
          "align-self-top",
          "custom-image",
        );
        expect(image).toHaveClass("mb-none", "fullwidth");
      });

      it("handles all variant and styling props together", () => {
        render(
          <PromoBanner
            variant="vertical"
            className="custom-banner"
            itemClassName="custom-item"
            image="test.jpg"
            imageClassName="custom-image"
          >
            Content
          </PromoBanner>,
        );

        const banner = document.querySelector(".promo-banner");
        const item = document.querySelector(".promo-banner__item");
        const imageContainer = document.querySelector(".promo-banner__image");

        expect(banner).toHaveClass("promo-banner", "custom-banner");
        expect(item).toHaveClass(
          "promo-banner__item",
          "align-items-center",
          "align-center",
          "align-self-center",
          "custom-item",
        );
        expect(imageContainer).toHaveClass(
          "promo-banner__image",
          "align-center",
          "custom-image",
        );
      });
    });

    describe("edge cases", () => {
      it("handles empty children", () => {
        render(<PromoBanner>{""}</PromoBanner>);
        const banner = document.querySelector(".promo-banner");
        expect(banner).toBeInTheDocument();
      });

      it("handles null children", () => {
        render(<PromoBanner>{null}</PromoBanner>);
        const banner = document.querySelector(".promo-banner");
        expect(banner).toBeInTheDocument();
      });

      it("handles undefined children", () => {
        render(<PromoBanner>{undefined}</PromoBanner>);
        const banner = document.querySelector(".promo-banner");
        expect(banner).toBeInTheDocument();
      });

      it("handles number children", () => {
        render(<PromoBanner>{42}</PromoBanner>);
        expect(screen.getByText("42")).toBeInTheDocument();
      });

      it("handles boolean children", () => {
        render(<PromoBanner>{true}</PromoBanner>);
        const banner = document.querySelector(".promo-banner");
        expect(banner).toBeInTheDocument();
      });

      it("handles array children", () => {
        render(<PromoBanner>{["Item 1", "Item 2", "Item 3"]}</PromoBanner>);
        expect(screen.getByText(/Item 1/)).toBeInTheDocument();
        expect(screen.getByText(/Item 2/)).toBeInTheDocument();
        expect(screen.getByText(/Item 3/)).toBeInTheDocument();
      });

      it("handles empty image URL", () => {
        render(<PromoBanner image="">Content</PromoBanner>);
        // Empty image URL should not render an image element
        expect(screen.queryByRole("img")).not.toBeInTheDocument();
      });

      it("handles invalid alignImage gracefully", () => {
        render(
          <PromoBanner image="test.jpg" alignImage="invalid">
            Content
          </PromoBanner>,
        );
        const imageContainer = document.querySelector(".promo-banner__image");
        expect(imageContainer).toHaveClass("promo-banner__image");
        // Invalid align values are passed through but shouldn't break the component
        expect(imageContainer).toHaveClass("align-self-invalid");
      });

      it("handles invalid variant gracefully", () => {
        render(<PromoBanner variant="invalid">Content</PromoBanner>);
        const contentCol = document
          .querySelector(".promo-banner__item")
          .closest(".grid__col");
        // Should use default horizontal behavior
        expect(contentCol).toHaveClass("grid__col");
        const item = document.querySelector(".promo-banner__item");
        expect(item).not.toHaveClass(
          "align-items-center",
          "align-center",
          "align-self-center",
        );
      });
    });

    describe("additional props", () => {
      it("applies custom className to banner", () => {
        render(<PromoBanner className="test-banner">Content</PromoBanner>);
        const banner = document.querySelector(".promo-banner");
        expect(banner).toHaveClass("promo-banner", "test-banner");
      });

      it("component structure is stable", () => {
        const { container } = render(<PromoBanner>Content</PromoBanner>);
        const banner = container.querySelector(".promo-banner");
        const item = container.querySelector(".promo-banner__item");

        expect(banner).toBeInTheDocument();
        expect(item).toBeInTheDocument();
        expect(banner).toHaveClass("promo-banner");
        expect(item).toHaveClass("promo-banner__item");
      });
    });
  });
});
