import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { axe } from "vitest-axe";

import { PromoBanner } from "../";

/**
 * PromoBanner Component Conformance Tests
 *
 * These tests verify the complete functionality of the PromoBanner component including:
 *
 * 🎯 HTML VALIDITY
 * - HTML validity with various prop combinations
 * - Semantic HTML structure
 * - Complex JSX structure validation
 * - Grid layout structure
 * - Image element validation
 *
 * ♿ ACCESSIBILITY (A11y)
 * - WCAG 2.1 compliance checks
 * - Proper use of semantic HTML elements
 * - Image alt attributes
 * - Interactive elements (buttons, links)
 * - Focus management and keyboard navigation
 * - Screen reader compatibility
 * - Color contrast compliance
 * - Grid layout accessibility
 *
 * 🎨 FUNCTIONAL BEHAVIOR
 * - Correct application of CSS classes (promo-banner)
 * - Color scheme variants: light, dark
 * - Layout variants: default (horizontal), vertical
 * - Image alignment: top, bottom
 * - Image bleeding effect
 * - Full width image functionality
 * - Custom className merging
 * - Grid and GridCol integration
 * - Image component integration
 *
 * 📝 CONTENT RENDERING
 * - Text children rendering
 * - Complex JSX children
 * - Multiple children
 * - Empty content handling
 * - Image rendering with various props
 *
 * ⚠️ EDGE CASES
 * - Null, undefined, boolean children
 * - Number and array children
 * - Invalid props graceful handling
 * - Empty image URLs
 * - Boundary usage cases
 *
 * 🔗 INTEGRATION TESTS
 * - Working with interactive elements
 * - Grid component integration
 * - Image component integration
 * - Event handling
 * - Focus management
 * - Responsive behavior
 */

describe("PromoBanner Component Conformance Tests", () => {
  describe("HTML Validity", () => {
    it("is valid HTML with default props", () => {
      const { container } = render(<PromoBanner />);
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with all props", () => {
      const { container } = render(
        <PromoBanner
          className="test-class"
          image="https://example.com/test.jpg"
          alignImage="top"
          bleedImage
          imageFullWidth
          variant="vertical"
          itemClassName="custom-item"
          imageClassName="custom-image"
          data-testid="test-promo-banner"
        >
          <h2>Promotion Title</h2>
          <p>Promotion description with detailed content</p>
          <button type="button">Call to Action</button>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with complex content structure", () => {
      const { container } = render(
        <PromoBanner image="https://example.com/banner.jpg">
          <header>
            <h1>Special Offer</h1>
            <p className="subtitle">Limited time promotion</p>
          </header>
          <main>
            <section>
              <h2>Details</h2>
              <p>
                Comprehensive promotion details with <strong>emphasis</strong>{" "}
                and <em>italic text</em>.
              </p>
              <ul>
                <li>Feature 1</li>
                <li>Feature 2</li>
                <li>Feature 3</li>
              </ul>
              <div>
                <button type="button">Primary Action</button>
                <button type="button">Secondary Action</button>
              </div>
            </section>
          </main>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with Grid layout structure", () => {
      const { container } = render(
        <PromoBanner>
          <div className="content-wrapper">
            <h2>Grid Layout Content</h2>
            <p>Content rendered within Grid component structure</p>
          </div>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with Image component", () => {
      const { container } = render(
        <PromoBanner image="https://example.com/test.jpg" alignImage="bottom">
          <h2>Content with Image</h2>
          <p>Banner with properly structured Image component</p>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with vertical variant", () => {
      const { container } = render(
        <PromoBanner
          variant="vertical"
          image="https://example.com/vertical.jpg"
        >
          <h2>Vertical Layout</h2>
          <p>Content in vertical layout structure</p>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with bleeding image", () => {
      const { container } = render(
        <PromoBanner image="https://example.com/bleed.jpg" bleedImage>
          <h2>Bleeding Image</h2>
          <p>Content with bleeding image effect</p>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with full width image", () => {
      const { container } = render(
        <PromoBanner
          variant="vertical"
          image="https://example.com/fullwidth.jpg"
          imageFullWidth
        >
          <h2>Full Width Image</h2>
          <p>Content with full width image</p>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with reverse variant", () => {
      const { container } = render(
        <PromoBanner variant="reverse" image="https://example.com/reverse.jpg">
          <h2>Reverse Layout</h2>
          <p>Content with reverse layout</p>
        </PromoBanner>,
      );
      expect(container).toHTMLValidate();
    });
  });

  describe("Accessibility (A11y)", () => {
    it("is accessible with default props", async () => {
      const { container } = render(
        <PromoBanner>
          <h2>Accessible Content</h2>
          <p>This content is accessible by default</p>
        </PromoBanner>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with all props", async () => {
      const { container } = render(
        <PromoBanner
          image="https://example.com/test.jpg"
          alignImage="top"
          bleedImage
          variant="vertical"
        >
          <h2>Accessible Banner</h2>
          <p>Banner content with all accessibility features</p>
          <button type="button">Accessible Button</button>
        </PromoBanner>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with complex interactive content", async () => {
      const { container } = render(
        <PromoBanner image="https://example.com/interactive.jpg">
          <h1>Interactive Promotion</h1>
          <p>
            Promotion with multiple interactive elements and proper
            accessibility
          </p>
          <form>
            <label htmlFor="email">Email Address</label>
            <input type="email" id="email" name="email" required />
            <button type="submit">Subscribe</button>
          </form>
          <nav aria-label="Promotion navigation">
            <ul>
              <li>
                <a href="#details">Details</a>
              </li>
              <li>
                <a href="#terms">Terms</a>
              </li>
              <li>
                <a href="#contact">Contact</a>
              </li>
            </ul>
          </nav>
        </PromoBanner>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("has proper image alt attribute", async () => {
      const { container } = render(
        <PromoBanner image="https://example.com/promo.jpg">
          <h2>Banner with Image</h2>
        </PromoBanner>,
      );

      const image = screen.getByRole("img");
      expect(image).toHaveAttribute("alt", "Obrázok");
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with heading hierarchy", async () => {
      const { container } = render(
        <PromoBanner>
          <h1>Main Banner Title</h1>
          <h2>Subtitle</h2>
          <h3>Section Title</h3>
          <p>Content with proper heading hierarchy</p>
        </PromoBanner>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with form elements", async () => {
      const { container } = render(
        <PromoBanner>
          <h2>Newsletter Signup</h2>
          <form>
            <fieldset>
              <legend>Contact Information</legend>
              <div>
                <label htmlFor="promo-name">Name</label>
                <input type="text" id="promo-name" name="name" required />
              </div>
              <div>
                <label htmlFor="promo-email">Email</label>
                <input type="email" id="promo-email" name="email" required />
              </div>
              <button type="submit">Submit</button>
            </fieldset>
          </form>
        </PromoBanner>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with ARIA attributes", async () => {
      const { container } = render(
        <PromoBanner>
          <div role="banner" aria-labelledby="promo-title">
            <h2 id="promo-title">Special Promotion</h2>
            <p aria-describedby="promo-details">Limited time offer</p>
            <div id="promo-details">
              Valid until end of month. Terms and conditions apply.
            </div>
            <button
              type="button"
              aria-expanded="false"
              aria-controls="promo-details"
            >
              Learn More
            </button>
          </div>
        </PromoBanner>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with reverse variant", async () => {
      const { container } = render(
        <PromoBanner variant="reverse" image="https://example.com/test.jpg">
          <h2>Accessible Reverse Layout</h2>
          <p>This content is accessible in reverse layout</p>
          <button type="button">Action Button</button>
        </PromoBanner>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });
  });

  describe("Functional Behavior", () => {
    it("applies correct CSS classes for default state", () => {
      const { container } = render(<PromoBanner>Content</PromoBanner>);

      const banner = container.querySelector(".promo-banner");
      const item = container.querySelector(".promo-banner__item");

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

    it("applies variant classes correctly", () => {
      const { container: horizontalContainer } = render(
        <PromoBanner>Horizontal Content</PromoBanner>,
      );
      const { container: verticalContainer } = render(
        <PromoBanner variant="vertical">Vertical Content</PromoBanner>,
      );
      const { container: reverseContainer } = render(
        <PromoBanner variant="reverse" image="test.jpg">
          Reverse Content
        </PromoBanner>,
      );

      const horizontalItem = horizontalContainer.querySelector(
        ".promo-banner__item",
      );
      const verticalItem = verticalContainer.querySelector(
        ".promo-banner__item",
      );
      const reverseItem = reverseContainer.querySelector(".promo-banner__item");

      expect(horizontalItem).not.toHaveClass(
        "align-items-center",
        "align-center",
        "align-self-center",
      );
      expect(verticalItem).toHaveClass(
        "align-items-center",
        "align-center",
        "align-self-center",
      );
      expect(reverseItem).not.toHaveClass(
        "align-items-center",
        "align-center",
        "align-self-center",
      );
    });

    it("applies image-related classes correctly", () => {
      const { container } = render(
        <PromoBanner
          image="test.jpg"
          alignImage="top"
          bleedImage
          imageFullWidth
        >
          Content
        </PromoBanner>,
      );

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

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

    it("merges custom classes correctly", () => {
      const { container } = render(
        <PromoBanner
          className="custom-banner"
          itemClassName="custom-item"
          imageClassName="custom-image"
          image="test.jpg"
        >
          Content
        </PromoBanner>,
      );

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

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

    it("handles Grid component integration correctly", () => {
      const { container } = render(<PromoBanner>Grid Content</PromoBanner>);

      const grid = container.querySelector(".grid");
      const gridCols = container.querySelectorAll(".grid__col");

      expect(grid).toBeInTheDocument();
      expect(gridCols).toHaveLength(1); // Only content column when no image
    });

    it("handles GridCol sizes correctly", () => {
      const { container: noImageContainer } = render(
        <PromoBanner>No image content</PromoBanner>,
      );
      const { container: withImageContainer } = render(
        <PromoBanner image="test.jpg">With image content</PromoBanner>,
      );
      const { container: verticalContainer } = render(
        <PromoBanner variant="vertical">Vertical content</PromoBanner>,
      );

      const noImageCol = noImageContainer.querySelector(".grid__col");
      const withImageContentCol = withImageContainer
        .querySelector(".promo-banner__item")
        .closest(".grid__col");
      const verticalCol = verticalContainer.querySelector(".grid__col");

      expect(noImageCol).toHaveClass("grid__col");
      expect(withImageContentCol).toHaveClass("grid__col");
      expect(verticalCol).toHaveClass("grid__col");
    });
  });

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

    it("renders complex JSX content correctly", () => {
      render(
        <PromoBanner>
          <div data-testid="complex-wrapper">
            <h1>Complex Title</h1>
            <p>
              Complex description with <strong>bold</strong> and <em>italic</em>{" "}
              text
            </p>
            <ul>
              <li>List item 1</li>
              <li>List item 2</li>
            </ul>
            <button type="button">Action Button</button>
          </div>
        </PromoBanner>,
      );

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

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

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

    it("renders image with correct attributes", () => {
      render(
        <PromoBanner image="https://example.com/banner.jpg" imageFullWidth>
          Content with image
        </PromoBanner>,
      );

      const image = screen.getByRole("img");
      expect(image).toHaveAttribute("src", "https://example.com/banner.jpg");
      expect(image).toHaveAttribute("alt", "Obrázok");
      expect(image).toHaveClass("mb-none", "fullwidth");
    });

    it("renders content without image correctly", () => {
      render(<PromoBanner>Content without image</PromoBanner>);

      expect(screen.getByText("Content without image")).toBeInTheDocument();
      expect(screen.queryByRole("img")).not.toBeInTheDocument();
    });

    it("handles dynamic content updates", () => {
      const { rerender } = render(<PromoBanner>Initial content</PromoBanner>);
      expect(screen.getByText("Initial content")).toBeInTheDocument();

      rerender(<PromoBanner>Updated content</PromoBanner>);
      expect(screen.getByText("Updated content")).toBeInTheDocument();
      expect(screen.queryByText("Initial content")).not.toBeInTheDocument();
    });
  });

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

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

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

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

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

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

    it("handles invalid alignImage prop gracefully", () => {
      const { container } = render(
        <PromoBanner image="test.jpg" alignImage="invalid">
          Content
        </PromoBanner>,
      );
      const imageContainer = container.querySelector(".promo-banner__image");
      expect(imageContainer).toHaveClass("promo-banner__image");
      // Invalid align values are passed through
      expect(imageContainer).toHaveClass("align-self-invalid");
    });

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

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

    it("handles very long content gracefully", () => {
      const longContent = "Very long content ".repeat(100);
      render(<PromoBanner>{longContent}</PromoBanner>);
      expect(screen.getByText(/Very long content/)).toBeInTheDocument();
    });

    it("handles special characters in content", () => {
      const specialContent =
        "Content with special chars: áčďéíľňóôšťúžý @#$%^&*()";
      render(<PromoBanner>{specialContent}</PromoBanner>);
      expect(screen.getByText(specialContent)).toBeInTheDocument();
    });
  });

  describe("Integration Tests", () => {
    it("works with interactive elements", async () => {
      const user = userEvent.setup();
      const handleClick = vi.fn();

      render(
        <PromoBanner>
          <h2>Interactive Banner</h2>
          <button type="button" onClick={handleClick}>
            Click me
          </button>
        </PromoBanner>,
      );

      const button = screen.getByRole("button");
      await user.click(button);
      expect(handleClick).toHaveBeenCalledTimes(1);
    });

    it("handles form submission within banner", async () => {
      const user = userEvent.setup();
      const handleSubmit = vi.fn((e) => e.preventDefault());

      render(
        <PromoBanner>
          <form onSubmit={handleSubmit}>
            <label htmlFor="test-input">Test Input</label>
            <input type="text" id="test-input" />
            <button type="submit">Submit</button>
          </form>
        </PromoBanner>,
      );

      const input = screen.getByLabelText("Test Input");
      const submitButton = screen.getByRole("button", { name: "Submit" });

      await user.type(input, "test value");
      await user.click(submitButton);

      expect(handleSubmit).toHaveBeenCalledTimes(1);
      expect(input).toHaveValue("test value");
    });

    it("handles focus management correctly", async () => {
      const user = userEvent.setup();

      render(
        <PromoBanner>
          <button type="button">Button 1</button>
          <button type="button">Button 2</button>
          <a href="#">Link</a>
        </PromoBanner>,
      );

      const button1 = screen.getByRole("button", { name: "Button 1" });
      const button2 = screen.getByRole("button", { name: "Button 2" });
      const link = screen.getByRole("link");

      await user.tab();
      expect(button1).toHaveFocus();

      await user.tab();
      expect(button2).toHaveFocus();

      await user.tab();
      expect(link).toHaveFocus();
    });

    it("works with keyboard navigation", async () => {
      const user = userEvent.setup();
      const handleClick = vi.fn();

      render(
        <PromoBanner>
          <button type="button" onClick={handleClick}>
            Keyboard accessible button
          </button>
        </PromoBanner>,
      );

      const button = screen.getByRole("button");
      button.focus();
      await user.keyboard("{Enter}");
      expect(handleClick).toHaveBeenCalledTimes(1);

      await user.keyboard(" ");
      expect(handleClick).toHaveBeenCalledTimes(2);
    });

    it("maintains proper Grid component behavior", () => {
      const { container } = render(
        <PromoBanner className="test-grid">
          <div>Grid content</div>
        </PromoBanner>,
      );

      const banner = container.querySelector(".promo-banner");
      const grid = banner.querySelector(".grid");
      const gridCol = container.querySelector(".grid__col");

      expect(banner).toHaveClass("promo-banner", "test-grid");
      expect(grid).toHaveClass("grid");
      expect(gridCol).toHaveClass("grid__col");
    });

    it("handles event propagation correctly", async () => {
      const user = userEvent.setup();
      const bannerClick = vi.fn();
      const buttonClick = vi.fn((e) => e.stopPropagation());

      render(
        <PromoBanner onClick={bannerClick}>
          <button type="button" onClick={buttonClick}>
            Stop propagation button
          </button>
        </PromoBanner>,
      );

      const button = screen.getByRole("button");
      await user.click(button);

      expect(buttonClick).toHaveBeenCalledTimes(1);
      expect(bannerClick).not.toHaveBeenCalled(); // Should be stopped
    });

    it("works with responsive image behavior", () => {
      render(
        <PromoBanner image="responsive.jpg" imageFullWidth>
          Responsive content
        </PromoBanner>,
      );

      const image = screen.getByRole("img");
      expect(image).toHaveClass("fullwidth");
      expect(image).toHaveAttribute("src", "responsive.jpg");
    });

    it("handles complex nested component structure", () => {
      render(
        <PromoBanner image="complex.jpg" variant="vertical">
          <header>
            <h1>Complex Structure</h1>
          </header>
          <main>
            <section>
              <h2>Section Title</h2>
              <article>
                <h3>Article Title</h3>
                <p>Article content</p>
              </article>
            </section>
          </main>
          <aside>
            <p>Sidebar content</p>
          </aside>
        </PromoBanner>,
      );

      expect(screen.getByRole("banner")).toBeInTheDocument();
      expect(screen.getByRole("main")).toBeInTheDocument();
      expect(screen.getByRole("complementary")).toBeInTheDocument();
      expect(screen.getByRole("article")).toBeInTheDocument();
    });
  });
});
