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

import { Section } from "../";

/**
 * Section Component Conformance Tests
 *
 * These tests verify the complete functionality of the Section component including:
 *
 * 🎯 HTML VALIDITY
 * - HTML validity with various prop combinations
 * - Semantic HTML tag correctness
 * - Complex JSX structure validation
 * - Container wrapper structure
 *
 * ♿ ACCESSIBILITY (A11y)
 * - WCAG 2.1 compliance checks
 * - Proper use of semantic HTML tags
 * - ARIA attributes and their validity
 * - Interactive elements (buttons, inputs, selects)
 * - Focus management and keyboard navigation
 * - Screen reader compatibility
 *
 * 🎨 FUNCTIONAL BEHAVIOR
 * - Correct application of CSS classes (section, section--*)
 * - All colors: background-primary (default), background-secondary, background-contrast, background-accent, etc.
 * - All spacing variants: default, small, xsmall
 * - Multiple props combinations
 * - Custom tag rendering (section, article, main, aside, header, footer)
 * - Passing through additional props (id, role, aria-*)
 * - Container integration and structure
 * - Text inverse functionality for background-contrast
 *
 * 📝 CONTENT RENDERING
 * - Text children rendering through Container
 * - Complex JSX children
 * - Multiple children
 * - Empty children
 *
 * ⚠️ EDGE CASES
 * - Null, undefined, boolean children
 * - Number and array children
 * - Invalid props graceful handling
 * - Boundary usage cases
 *
 * 🔗 INTEGRATION TESTS
 * - Working with form elements
 * - Interactive components
 * - Event handling
 * - Focus management
 * - User interactions using userEvent
 *
 * 📊 TEST COVERAGE
 * - All props: color, spacing, tag, className, children
 * - All color and spacing variants
 * - All supported HTML tags
 * - Accessibility violations
 * - HTML validation errors
 * - User interaction scenarios
 * - Container wrapper functionality
 */

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

    it("is valid HTML with all props", () => {
      const { container } = render(
        <Section
          color="background-secondary"
          spacing="small"
          tag="section"
          className="test-class"
          data-testid="test-section"
        >
          <h2>Test Content</h2>
          <p>Test paragraph</p>
        </Section>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with custom tag", () => {
      const { container } = render(
        <Section tag="article">
          <h1>Article Title</h1>
        </Section>,
      );
      expect(container).toHTMLValidate();
    });

    it("is valid HTML with Container wrapper", () => {
      const { container } = render(
        <Section>
          <div>Content wrapped in Container</div>
        </Section>,
      );
      expect(container).toHTMLValidate();
    });
  });

  describe("Accessibility", () => {
    it("is accessible with default props", async () => {
      const { container } = render(<Section />);
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with semantic HTML tag", async () => {
      const { container } = render(
        <Section tag="main">
          <h1>Main Content</h1>
        </Section>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with complex content", async () => {
      const { container } = render(
        <Section color="background-secondary" spacing="small">
          <header>
            <h1>Page Title</h1>
            <nav aria-label="Main navigation">
              <ul>
                <li>
                  <a href="#home">Home</a>
                </li>
                <li>
                  <a href="#about">About</a>
                </li>
              </ul>
            </nav>
          </header>
          <main>
            <article>
              <h2>Article Title</h2>
              <p>
                Article content with <a href="#link">link</a>.
              </p>
            </article>
          </main>
        </Section>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with interactive elements", async () => {
      const { container } = render(
        <Section>
          <button type="button">Click me</button>
          <input type="text" aria-label="Search" />
          <select aria-label="Choose option">
            <option value="1">Option 1</option>
            <option value="2">Option 2</option>
          </select>
        </Section>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with ARIA attributes", async () => {
      const { container } = render(
        <Section
          tag="section"
          aria-labelledby="section-title"
          aria-describedby="section-description"
        >
          <h2 id="section-title">Section Title</h2>
          <p id="section-description">Section description</p>
        </Section>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });

    it("is accessible with Container wrapper", async () => {
      const { container } = render(
        <Section>
          <div role="main">
            <h1>Main Content</h1>
            <p>Content wrapped in Container</p>
          </div>
        </Section>,
      );
      expect(await axe(container)).toHaveNoViolations();
    });
  });

  describe("Functional Behavior", () => {
    it("renders with correct default classes", () => {
      const { container } = render(<Section data-testid="test-section" />);
      const section = container.querySelector('[data-testid="test-section"]');
      expect(section).toHaveClass("section");
      expect(section).not.toHaveClass("background-primary");
    });

    it("applies color classes correctly", () => {
      const colors = [
        "background-secondary",
        "background-accent",
        "background-accent1-blog",
        "background-accent2-blog",
        "accent1-blog",
        "accent2-blog",
      ];
      colors.forEach((color) => {
        const { container } = render(
          <Section color={color} data-testid="test-section" />,
        );
        const section = container.querySelector('[data-testid="test-section"]');
        expect(section).toHaveClass(color);
      });
    });

    it("applies background-contrast with text-inverse correctly", () => {
      const { container } = render(
        <Section color="background-contrast" data-testid="test-section" />,
      );
      const section = container.querySelector('[data-testid="test-section"]');
      expect(section).toHaveClass("background-contrast");
      expect(section).toHaveClass("text-inverse");
    });

    it("applies spacing classes correctly", () => {
      const spacings = ["default", "small", "xsmall"];
      spacings.forEach((spacing) => {
        const { container } = render(
          <Section spacing={spacing} data-testid="test-section" />,
        );
        const section = container.querySelector('[data-testid="test-section"]');
        expect(section).toHaveClass(`section--${spacing}`);
      });
    });

    it("combines multiple props correctly", () => {
      const { container } = render(
        <Section
          color="background-secondary"
          spacing="small"
          className="custom-class"
          data-testid="test-section"
        />,
      );
      const section = container.querySelector('[data-testid="test-section"]');
      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-secondary");
      expect(section).toHaveClass("section--small");
      expect(section).toHaveClass("custom-class");
    });

    it("renders with custom tag", () => {
      const tags = ["section", "article", "main", "aside", "header", "footer"];
      tags.forEach((tag) => {
        const { container } = render(
          <Section tag={tag} data-testid="test-section" />,
        );
        const element = container.querySelector(`[data-testid="test-section"]`);
        expect(element.tagName.toLowerCase()).toBe(tag);
      });
    });

    it("passes through additional props", () => {
      const { container } = render(
        <Section
          data-testid="test-section"
          id="test-id"
          role="banner"
          aria-label="Test section"
        />,
      );
      const section = container.querySelector('[data-testid="test-section"]');
      expect(section).toHaveAttribute("id", "test-id");
      expect(section).toHaveAttribute("role", "banner");
      expect(section).toHaveAttribute("aria-label", "Test section");
    });

    it("renders Container wrapper when children are provided", () => {
      const { container } = render(
        <Section data-testid="test-section">
          <p>Test content</p>
        </Section>,
      );
      const section = container.querySelector('[data-testid="test-section"]');
      const containerElement = section.querySelector(".container");

      expect(containerElement).toBeInTheDocument();
      expect(containerElement).toHaveClass("container");
      expect(containerElement).toContainElement(
        screen.getByText("Test content"),
      );
    });

    it("does not render Container wrapper when no children", () => {
      const { container } = render(<Section data-testid="test-section" />);
      const section = container.querySelector('[data-testid="test-section"]');
      const containerElement = section.querySelector(".container");

      expect(section.children.length).toBe(1);
      expect(containerElement).toBeInTheDocument();
      expect(containerElement).toHaveClass("container");
      expect(containerElement.children.length).toBe(0);
    });
  });

  describe("Content Rendering", () => {
    it("renders text children through Container", () => {
      render(<Section>Test content</Section>);
      expect(screen.getByText("Test content")).toBeInTheDocument();
    });

    it("renders complex JSX children through Container", () => {
      render(
        <Section>
          <h1>Title</h1>
          <p>
            Paragraph with <strong>bold text</strong>
          </p>
          <ul>
            <li>Item 1</li>
            <li>Item 2</li>
          </ul>
        </Section>,
      );
      expect(screen.getByText("Title")).toBeInTheDocument();
      expect(screen.getByText("Paragraph with")).toBeInTheDocument();
      expect(screen.getByText("bold text")).toBeInTheDocument();
      expect(screen.getByText("Item 1")).toBeInTheDocument();
      expect(screen.getByText("Item 2")).toBeInTheDocument();
    });

    it("renders multiple children through Container", () => {
      render(
        <Section>
          <div>Child 1</div>
          <div>Child 2</div>
          <div>Child 3</div>
        </Section>,
      );
      expect(screen.getByText("Child 1")).toBeInTheDocument();
      expect(screen.getByText("Child 2")).toBeInTheDocument();
      expect(screen.getByText("Child 3")).toBeInTheDocument();
    });

    it("renders empty children", () => {
      const { container } = render(<Section />);
      const section = container.querySelector(".section");
      const containerElement = section.querySelector(".container");

      expect(section).toBeInTheDocument();
      expect(containerElement).toBeInTheDocument();
      expect(containerElement.children.length).toBe(0);
    });

    it("renders Container with proper structure", () => {
      const { container } = render(
        <Section>
          <h1>Test Title</h1>
          <p>Test paragraph</p>
        </Section>,
      );
      const section = container.querySelector(".section");
      const containerElement = section.querySelector(".container");

      expect(containerElement).toBeInTheDocument();
      expect(containerElement).toHaveClass("container");
      expect(containerElement).toContainElement(screen.getByText("Test Title"));
      expect(containerElement).toContainElement(
        screen.getByText("Test paragraph"),
      );
    });
  });

  describe("Edge Cases", () => {
    it("handles null children", () => {
      const { container } = render(<Section>{null}</Section>);
      const section = container.querySelector(".section");
      expect(section).toBeInTheDocument();
    });

    it("handles undefined children", () => {
      const { container } = render(<Section>{undefined}</Section>);
      const section = container.querySelector(".section");
      expect(section).toBeInTheDocument();
    });

    it("handles boolean children", () => {
      const { container } = render(<Section>{true}</Section>);
      const section = container.querySelector(".section");
      expect(section).toBeInTheDocument();
    });

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

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

    it("handles invalid color prop gracefully", () => {
      const { container } = render(
        <Section color="invalid-color" data-testid="test-section" />,
      );
      const section = container.querySelector('[data-testid="test-section"]');
      expect(section).toHaveClass("section");
      expect(section).toHaveClass("invalid-color");
    });

    it("handles invalid spacing prop gracefully", () => {
      const { container } = render(
        <Section spacing="invalid-spacing" data-testid="test-section" />,
      );
      const section = container.querySelector('[data-testid="test-section"]');
      expect(section).toHaveClass("section");
      expect(section).toHaveClass("section--invalid-spacing");
    });
  });

  describe("Integration Tests", () => {
    it("works with form elements", async () => {
      const user = userEvent.setup();
      render(
        <Section>
          <form>
            <input type="text" data-testid="input" />
            <button type="button" data-testid="button">
              Click me
            </button>
          </form>
        </Section>,
      );

      const input = screen.getByTestId("input");
      const button = screen.getByTestId("button");

      await user.type(input, "test value");
      expect(input).toHaveValue("test value");

      await user.click(button);
      // Button click should work without form submission
    });

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

      render(
        <Section>
          <button onClick={handleClick} data-testid="button">
            Click me
          </button>
        </Section>,
      );

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

      expect(handleClick).toHaveBeenCalledTimes(1);
    });

    it("maintains focus management", async () => {
      const user = userEvent.setup();
      render(
        <Section>
          <button data-testid="button1">Button 1</button>
          <button data-testid="button2">Button 2</button>
        </Section>,
      );

      const button1 = screen.getByTestId("button1");
      const button2 = screen.getByTestId("button2");

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

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

    it("works with Container wrapper for complex interactions", async () => {
      const user = userEvent.setup();
      const handleSubmit = vi.fn((e) => {
        e.preventDefault();
      });

      render(
        <Section>
          <form onSubmit={handleSubmit}>
            <input type="text" data-testid="name-input" placeholder="Name" />
            <input type="email" data-testid="email-input" placeholder="Email" />
            <button type="submit" data-testid="submit-btn">
              Submit
            </button>
          </form>
        </Section>,
      );

      const nameInput = screen.getByTestId("name-input");
      const emailInput = screen.getByTestId("email-input");
      const submitBtn = screen.getByTestId("submit-btn");

      await user.type(nameInput, "John Doe");
      await user.type(emailInput, "john@example.com");
      await user.click(submitBtn);

      expect(nameInput).toHaveValue("John Doe");
      expect(emailInput).toHaveValue("john@example.com");
      expect(handleSubmit).toHaveBeenCalledTimes(1);
    });
  });
});
