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

import { Section } from "../Section";

/**
 * Section Component Unit Tests
 *
 * These unit tests focus on testing individual functionality and behavior
 * of the Section component in isolation. They cover:
 *
 * 🏗️ COMPONENT STRUCTURE
 * - Default rendering behavior
 * - CSS class application
 * - HTML element rendering
 * - Component initialization
 * - Container wrapper structure
 *
 * 🎨 STYLING & CLASSES
 * - Base CSS class application
 * - Color-based class generation
 * - Spacing variant classes
 * - Custom className merging
 * - Conditional class application
 *
 * 🔧 PROPS HANDLING
 * - Individual prop testing
 * - Prop combinations
 * - Default prop values
 * - Prop validation and fallbacks
 * - Custom tag rendering
 *
 * 📦 CONTENT RENDERING
 * - Children rendering through Container
 * - Text content
 * - JSX content
 * - Empty content handling
 * - Multiple children
 *
 * 🎯 SPECIFIC FUNCTIONALITY
 * - Color prop behavior (background-secondary, background-contrast, background-accent, etc.)
 * - Spacing prop behavior (default, small, xsmall)
 * - Tag prop behavior (div, section, article, etc.)
 * - ClassName prop merging
 * - Additional props spreading
 * - Container integration
 * - Text inverse functionality for background-contrast
 *
 * ⚡ PERFORMANCE & OPTIMIZATION
 * - Component re-rendering
 * - Prop change handling
 * - Memory usage patterns
 * - Bundle size impact
 *
 * 🔍 DETAILED ASSERTIONS
 * - Exact class presence/absence
 * - Element count verification
 * - Attribute validation
 * - Content accuracy
 * - DOM structure integrity
 */

describe("Section Component Unit Tests", () => {
  describe("Component Structure & Initialization", () => {
    it("renders with default structure and base class", () => {
      const { getByTestId } = render(<Section data-testid="test-section" />);
      const section = getByTestId("test-section");

      expect(section).toBeInTheDocument();
      expect(section).toHaveClass("section");
      expect(section.tagName.toLowerCase()).toBe("div");
    });

    it("renders with 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(section).toBeInTheDocument();
      expect(containerElement).toBeInTheDocument();
      expect(containerElement).toHaveClass("container");
      expect(containerElement).toContainElement(
        screen.getByText("Test content"),
      );
    });

    it("renders without 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);
    });

    it("maintains component structure with various props", () => {
      const { getByTestId } = render(
        <Section
          data-testid="test-section"
          color="background-secondary"
          spacing="small"
          className="custom-class"
        />,
      );
      const section = getByTestId("test-section");

      expect(section).toBeInTheDocument();
      expect(section).toHaveClass("section");
      expect(section.tagName.toLowerCase()).toBe("div");
    });
  });

  describe("CSS Classes & Styling", () => {
    it("applies base section class correctly", () => {
      const { getByTestId } = render(<Section data-testid="test-section" />);
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
    });

    it("merges custom className with base class", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" className="custom-class" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("custom-class");
    });

    it("handles multiple custom classes", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" className="class1 class2 class3" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("class1");
      expect(section).toHaveClass("class2");
      expect(section).toHaveClass("class3");
    });

    it("handles empty className gracefully", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" className="" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
    });
  });

  describe("Color Prop Behavior", () => {
    it("applies correct color class for background-secondary color", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="background-secondary" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-secondary");
    });

    it("applies correct color class and text-inverse for background-contrast color", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="background-contrast" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-contrast");
      expect(section).toHaveClass("text-inverse");
    });

    it("applies correct color class for background-accent color", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="background-accent" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-accent");
    });

    it("applies correct color class for background-accent1-blog color", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="background-accent1-blog" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-accent1-blog");
    });

    it("applies correct color class for background-accent2-blog color", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="background-accent2-blog" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-accent2-blog");
    });

    it("applies correct color class for accent1-blog color", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="accent1-blog" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("accent1-blog");
    });

    it("applies correct color class for accent2-blog color", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="accent2-blog" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("accent2-blog");
    });

    it("handles all color variants correctly", () => {
      const colors = [
        "background-secondary",
        "background-contrast",
        "background-accent",
        "background-accent1-blog",
        "background-accent2-blog",
        "background-none",
        "surface-subtle",
        "accent1-blog",
        "accent2-blog",
      ];

      colors.forEach((color, index) => {
        const { getByTestId } = render(
          <Section data-testid={`test-section-${index}`} color={color} />,
        );
        const section = getByTestId(`test-section-${index}`);

        expect(section).toHaveClass("section");

        if (color === "background-contrast") {
          expect(section).toHaveClass("background-contrast");
          expect(section).toHaveClass("text-inverse");
        } else {
          expect(section).toHaveClass(color);
        }
      });
    });
  });

  describe("Spacing Prop Behavior", () => {
    it("applies no spacing class when spacing is not provided", () => {
      const { getByTestId } = render(<Section data-testid="test-section" />);
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).not.toHaveClass("section--default");
      expect(section).not.toHaveClass("section--small");
      expect(section).not.toHaveClass("section--xsmall");
    });

    it("applies correct spacing class for default spacing", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" spacing="default" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("section--default");
    });

    it("applies correct spacing class for small spacing", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" spacing="small" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("section--small");
    });

    it("applies correct spacing class for xsmall spacing", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" spacing="xsmall" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("section--xsmall");
    });

    it("handles all spacing variants correctly", () => {
      const spacings = ["default", "small", "xsmall"];

      spacings.forEach((spacing, index) => {
        const { getByTestId } = render(
          <Section data-testid={`test-section-${index}`} spacing={spacing} />,
        );
        const section = getByTestId(`test-section-${index}`);

        expect(section).toHaveClass("section");
        expect(section).toHaveClass(`section--${spacing}`);
      });
    });
  });

  describe("Tag Prop Behavior", () => {
    it("renders as div by default", () => {
      const { getByTestId } = render(<Section data-testid="test-section" />);
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("div");
    });

    it("renders as section when tag is section", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" tag="section" />,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("section");
    });

    it("renders as article when tag is article", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" tag="article" />,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("article");
    });

    it("renders as main when tag is main", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" tag="main" />,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("main");
    });

    it("renders as aside when tag is aside", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" tag="aside" />,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("aside");
    });

    it("renders as header when tag is header", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" tag="header" />,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("header");
    });

    it("renders as footer when tag is footer", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" tag="footer" />,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("footer");
    });

    it("handles all semantic HTML tags correctly", () => {
      const tags = [
        "div",
        "section",
        "article",
        "main",
        "aside",
        "header",
        "footer",
      ];

      tags.forEach((tag, index) => {
        const { getByTestId } = render(
          <Section data-testid={`test-section-${index}`} tag={tag} />,
        );
        const section = getByTestId(`test-section-${index}`);

        expect(section.tagName.toLowerCase()).toBe(tag);
        expect(section).toHaveClass("section");
      });
    });
  });

  describe("Content Rendering", () => {
    it("renders text children correctly through Container", () => {
      render(<Section data-testid="test-section">Simple text content</Section>);

      expect(screen.getByText("Simple text content")).toBeInTheDocument();
    });

    it("renders JSX children correctly through Container", () => {
      render(
        <Section data-testid="test-section">
          <h1>Title</h1>
          <p>Paragraph content</p>
        </Section>,
      );

      expect(screen.getByText("Title")).toBeInTheDocument();
      expect(screen.getByText("Paragraph content")).toBeInTheDocument();
    });

    it("renders multiple children correctly through Container", () => {
      render(
        <Section data-testid="test-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 complex nested JSX correctly through Container", () => {
      render(
        <Section data-testid="test-section">
          <header>
            <h1>Page Header</h1>
            <nav>
              <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 <strong>bold text</strong>.
              </p>
            </article>
          </main>
        </Section>,
      );

      expect(screen.getByText("Page Header")).toBeInTheDocument();
      expect(screen.getByText("Home")).toBeInTheDocument();
      expect(screen.getByText("About")).toBeInTheDocument();
      expect(screen.getByText("Article Title")).toBeInTheDocument();
      expect(screen.getByText(/Article content with/)).toBeInTheDocument();
      expect(screen.getByText("bold text")).toBeInTheDocument();
    });

    it("handles empty children gracefully", () => {
      const { getByTestId } = render(<Section data-testid="test-section" />);
      const section = getByTestId("test-section");
      const containerElement = section.querySelector(".container");

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

    it("handles null children gracefully", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section">{null}</Section>,
      );
      const section = getByTestId("test-section");

      expect(section).toBeInTheDocument();
    });

    it("handles undefined children gracefully", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section">{undefined}</Section>,
      );
      const section = getByTestId("test-section");

      expect(section).toBeInTheDocument();
    });

    it("renders Container with proper class 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"),
      );
    });
  });

  describe("Props Combinations", () => {
    it("combines color and spacing props correctly", () => {
      const { getByTestId } = render(
        <Section
          data-testid="test-section"
          color="background-secondary"
          spacing="small"
        />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-secondary");
      expect(section).toHaveClass("section--small");
    });

    it("combines color, spacing, and custom tag correctly", () => {
      const { getByTestId } = render(
        <Section
          data-testid="test-section"
          color="background-contrast"
          spacing="xsmall"
          tag="article"
        />,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("article");
      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-contrast");
      expect(section).toHaveClass("text-inverse");
      expect(section).toHaveClass("section--xsmall");
    });

    it("combines all props correctly", () => {
      const { getByTestId } = render(
        <Section
          data-testid="test-section"
          color="background-accent"
          spacing="default"
          tag="main"
          className="custom-class"
        >
          <h1>Content</h1>
        </Section>,
      );
      const section = getByTestId("test-section");

      expect(section.tagName.toLowerCase()).toBe("main");
      expect(section).toHaveClass("section");
      expect(section).toHaveClass("background-accent");
      expect(section).toHaveClass("section--default");
      expect(section).toHaveClass("custom-class");
      expect(screen.getByText("Content")).toBeInTheDocument();
    });
  });

  describe("Additional Props Spreading", () => {
    it("passes through id attribute", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" id="section-id" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveAttribute("id", "section-id");
    });

    it("passes through role attribute", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" role="banner" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveAttribute("role", "banner");
    });

    it("passes through aria attributes", () => {
      const { getByTestId } = render(
        <Section
          data-testid="test-section"
          aria-label="Test section"
          aria-describedby="description"
        />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveAttribute("aria-label", "Test section");
      expect(section).toHaveAttribute("aria-describedby", "description");
    });

    it("passes through data attributes", () => {
      const { getByTestId } = render(
        <Section
          data-testid="test-section"
          data-custom="value"
          data-another="another-value"
        />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveAttribute("data-custom", "value");
      expect(section).toHaveAttribute("data-another", "another-value");
    });

    it("passes through event handlers", () => {
      const handleClick = vi.fn();
      const { getByTestId } = render(
        <Section data-testid="test-section" onClick={handleClick} />,
      );
      const section = getByTestId("test-section");

      expect(section).toBeInTheDocument();
      // Event handler is attached but not tested here as it's unit test
    });
  });

  describe("Edge Cases & Error Handling", () => {
    it("handles invalid color prop gracefully", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" color="invalid-color" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("invalid-color");
    });

    it("handles invalid spacing prop gracefully", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" spacing="invalid-spacing" />,
      );
      const section = getByTestId("test-section");

      expect(section).toHaveClass("section");
      expect(section).toHaveClass("section--invalid-spacing");
    });

    it("handles invalid tag prop gracefully", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section" tag="invalid-tag" />,
      );
      const section = getByTestId("test-section");

      expect(section).toBeInTheDocument();
      // Invalid tag should fallback to div or handle gracefully
    });

    it("handles boolean children", () => {
      const { getByTestId } = render(
        <Section data-testid="test-section">{true}</Section>,
      );
      const section = getByTestId("test-section");

      expect(section).toBeInTheDocument();
    });

    it("handles number children", () => {
      render(<Section data-testid="test-section">{42}</Section>);

      expect(screen.getByText("42")).toBeInTheDocument();
    });

    it("handles array children", () => {
      render(
        <Section data-testid="test-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();
    });
  });
});
