/**
 * Unit tests for the Container component
 *
 * Covered use cases:
 * 1. Rendering:
 *    - Renders without crashing
 *    - Renders as a div element
 *    - Renders children (single, multiple, null, undefined, empty)
 * 2. CSS Classes:
 *    - Applies default and custom className(s)
 *    - Handles multiple, empty, whitespace, special, long, and numeric class names
 * 3. Props Forwarding:
 *    - Forwards standard HTML attributes (id, data-*, title, style, etc.)
 *    - Forwards event handlers (onClick, onMouseEnter, etc.)
 *    - Forwards ref to the underlying div
 *    - Forwards all standard HTML div props (tabIndex, role, aria-*)
 * 4. Component Behavior:
 *    - Maintains displayName
 *    - Works with React.memo
 *    - Handles complex and conditional children structures
 * 5. Edge Cases:
 *    - Handles very long className
 *    - Handles className with numbers
 *    - Handles array of children
 *    - Handles React elements as children
 */

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

import { Container } from "../";

describe("Container Component", () => {
  describe("Rendering", () => {
    it("should render without crashing", () => {
      const { container } = render(<Container />);
      expect(container.firstChild).toBeInTheDocument();
    });

    it("should render as a div element", () => {
      const { container } = render(<Container />);
      expect(container.firstChild.tagName).toBe("DIV");
    });

    it("should have the correct default class", () => {
      const { container } = render(<Container />);
      expect(container.firstChild).toHaveClass("container");
    });

    it("should render children correctly", () => {
      const testContent = "Test content";
      render(<Container>{testContent}</Container>);
      expect(screen.getByText(testContent)).toBeInTheDocument();
    });

    it("should render multiple children", () => {
      render(
        <Container>
          <div>First child</div>
          <p>Second child</p>
          <span>Third child</span>
        </Container>,
      );

      expect(screen.getByText("First child")).toBeInTheDocument();
      expect(screen.getByText("Second child")).toBeInTheDocument();
      expect(screen.getByText("Third child")).toBeInTheDocument();
    });

    it("should render empty children gracefully", () => {
      const { container } = render(<Container>{}</Container>);
      expect(container.firstChild).toBeInTheDocument();
      expect(container.firstChild).toHaveClass("container");
    });

    it("should render null children gracefully", () => {
      const { container } = render(<Container>{null}</Container>);
      expect(container.firstChild).toBeInTheDocument();
      expect(container.firstChild).toHaveClass("container");
    });

    it("should render undefined children gracefully", () => {
      const { container } = render(<Container>{undefined}</Container>);
      expect(container.firstChild).toBeInTheDocument();
      expect(container.firstChild).toHaveClass("container");
    });
  });

  describe("CSS Classes", () => {
    it("should apply custom className in addition to default class", () => {
      const { container } = render(<Container className="custom-class" />);
      const element = container.firstChild;

      expect(element).toHaveClass("container");
      expect(element).toHaveClass("custom-class");
    });

    it("should handle multiple custom classes", () => {
      const { container } = render(
        <Container className="class1 class2 class3" />,
      );
      const element = container.firstChild;

      expect(element).toHaveClass("container");
      expect(element).toHaveClass("class1");
      expect(element).toHaveClass("class2");
      expect(element).toHaveClass("class3");
    });

    it("should handle empty className", () => {
      const { container } = render(<Container className="" />);
      const element = container.firstChild;

      expect(element).toHaveClass("container");
    });

    it("should handle whitespace-only className", () => {
      const { container } = render(<Container className="   " />);
      const element = container.firstChild;

      expect(element).toHaveClass("container");
    });

    it("should handle className with special characters", () => {
      const { container } = render(
        <Container className="class-with-dash class_with_underscore" />,
      );
      const element = container.firstChild;

      expect(element).toHaveClass("container");
      expect(element).toHaveClass("class-with-dash");
      expect(element).toHaveClass("class_with_underscore");
    });
  });

  describe("Props Forwarding", () => {
    it("should forward HTML attributes", () => {
      const { container } = render(
        <Container
          id="test-id"
          data-testid="container"
          title="Test container"
        />,
      );
      const element = container.firstChild;

      expect(element).toHaveAttribute("id", "test-id");
      expect(element).toHaveAttribute("data-testid", "container");
      expect(element).toHaveAttribute("title", "Test container");
    });

    it("should forward event handlers", async () => {
      const user = userEvent.setup();
      const handleClick = vi.fn();
      const handleMouseEnter = vi.fn();

      render(
        <Container
          onClick={handleClick}
          onMouseEnter={handleMouseEnter}
          data-testid="container"
        />,
      );

      const container = screen.getByTestId("container");

      await user.click(container);
      expect(handleClick).toHaveBeenCalledTimes(1);

      // Reset mock before testing mouseEnter
      handleMouseEnter.mockClear();
      fireEvent.mouseEnter(container);
      expect(handleMouseEnter).toHaveBeenCalledTimes(1);
    });

    it("should forward ref correctly", () => {
      const ref = React.createRef();
      render(<Container ref={ref} />);

      expect(ref.current).toBeInstanceOf(HTMLDivElement);
      expect(ref.current).toHaveClass("container");
    });

    it("should forward all standard HTML div props", () => {
      const { container } = render(
        <Container
          id="test"
          className="custom"
          style={{ color: "red" }}
          onClick={() => {}}
          onFocus={() => {}}
          onBlur={() => {}}
          tabIndex={0}
          role="main"
          aria-label="Main content"
        />,
      );
      const element = container.firstChild;

      expect(element).toHaveAttribute("id", "test");
      expect(element).toHaveAttribute("tabindex", "0");
      expect(element).toHaveAttribute("role", "main");
      expect(element).toHaveAttribute("aria-label", "Main content");
    });
  });

  describe("Component Behavior", () => {
    it("should maintain displayName", () => {
      expect(Container.displayName).toBe("Container");
    });

    it("should work with React.memo if wrapped", () => {
      const MemoizedContainer = React.memo(Container);
      const { container } = render(<MemoizedContainer />);

      expect(container.firstChild).toBeInTheDocument();
      expect(container.firstChild).toHaveClass("container");
    });

    it("should handle complex nested structures", () => {
      render(
        <Container>
          <header>
            <h1>Title</h1>
            <nav>
              <ul>
                <li>
                  <a href="#home">Home</a>
                </li>
                <li>
                  <a href="#about">About</a>
                </li>
              </ul>
            </nav>
          </header>
          <main>
            <section>
              <h2>Section</h2>
              <p>Content</p>
            </section>
          </main>
        </Container>,
      );

      expect(screen.getByText("Title")).toBeInTheDocument();
      expect(screen.getByText("Home")).toBeInTheDocument();
      expect(screen.getByText("About")).toBeInTheDocument();
      expect(screen.getByText("Section")).toBeInTheDocument();
      expect(screen.getByText("Content")).toBeInTheDocument();
    });

    it("should handle conditional rendering of children", () => {
      const shouldRender = true;
      const { rerender } = render(
        <Container>{shouldRender && <div>Conditional content</div>}</Container>,
      );

      expect(screen.getByText("Conditional content")).toBeInTheDocument();

      rerender(
        <Container>{false && <div>Conditional content</div>}</Container>,
      );

      expect(screen.queryByText("Conditional content")).not.toBeInTheDocument();
    });
  });

  describe("Edge Cases", () => {
    it("should handle very long className", () => {
      const longClassName = "a".repeat(1000);
      const { container } = render(<Container className={longClassName} />);
      const element = container.firstChild;

      expect(element).toHaveClass("container");
      expect(element).toHaveClass(longClassName);
    });

    it("should handle className with numbers", () => {
      const { container } = render(<Container className="class123 456class" />);
      const element = container.firstChild;

      expect(element).toHaveClass("container");
      expect(element).toHaveClass("class123");
      expect(element).toHaveClass("456class");
    });

    it("should handle array as children", () => {
      const childrenArray = [
        <div key="1">Array child 1</div>,
        <div key="2">Array child 2</div>,
      ];

      render(<Container>{childrenArray}</Container>);

      expect(screen.getByText("Array child 1")).toBeInTheDocument();
      expect(screen.getByText("Array child 2")).toBeInTheDocument();
    });

    it("should handle React elements as children", () => {
      const ChildComponent = () => <div>React component child</div>;

      render(
        <Container>
          <ChildComponent />
        </Container>,
      );

      expect(screen.getByText("React component child")).toBeInTheDocument();
    });
  });
});
