/**
 * GridCol component unit tests
 *
 * This test suite verifies the rendering, props, and className logic of the GridCol component.
 * It checks default rendering, tag rendering, className merging, and all supported props (align, size, etc).
 * Also includes complex scenarios with various size combinations and responsive behavior.
 */

import { render } from "@testing-library/react";
import { GridCol } from "../GridCol";

describe("GridCol", () => {
  it("renders with default class grid__col", () => {
    const { getByTestId } = render(<GridCol data-testid="test-id" />);
    expect(getByTestId("test-id")).toHaveClass("grid__col");
  });

  it("renders with default tag div", () => {
    const { container } = render(<GridCol />);
    expect(container.querySelector("div")).toBeTruthy();
  });

  it("renders children", () => {
    const { getByText } = render(<GridCol>test</GridCol>);
    expect(getByText("test")).toBeInTheDocument();
  });

  it("renders with custom tag", () => {
    const { container } = render(<GridCol tag="span" />);
    expect(container.querySelector("span")).toBeTruthy();
  });

  it("merges additional className", () => {
    const { getByTestId } = render(
      <GridCol data-testid="test-id" className="test-class" />,
    );
    expect(getByTestId("test-id")).toHaveClass("test-class");
  });

  ["shrink", "fill", "auto"].forEach((size) => {
    it(`applies grid__col--${size} class when size is ${size}`, () => {
      const { getByTestId } = render(
        <GridCol data-testid="test-id" size={size} />,
      );
      expect(getByTestId("test-id")).toHaveClass(`grid__col--${size}`);
    });
  });

  ["top", "middle", "bottom", "stretch"].forEach((align) => {
    it(`applies align-self-${align} class when align is ${align}`, () => {
      const { getByTestId } = render(
        <GridCol data-testid="test-id" align={align} />,
      );
      expect(getByTestId("test-id")).toHaveClass(`align-self-${align}`);
    });
  });

  it("applies grid__col--3 class when size is number 3", () => {
    const { getByTestId } = render(<GridCol data-testid="test-id" size={3} />);
    expect(getByTestId("test-id")).toHaveClass("grid__col--3");
  });

  it("spreads additional props to the rendered element", () => {
    const { getByTestId } = render(
      <GridCol data-testid="test-id" id="my-col" data-extra="foo" />,
    );
    const el = getByTestId("test-id");
    expect(el).toHaveAttribute("id", "my-col");
    expect(el).toHaveAttribute("data-extra", "foo");
  });
});

describe("GridCol complex scenarios", () => {
  it("renders with all numeric sizes from 1 to 12", () => {
    for (let size = 1; size <= 12; size++) {
      const { getByTestId } = render(
        <GridCol data-testid={`test-${size}`} size={size} />,
      );
      expect(getByTestId(`test-${size}`)).toHaveClass(`grid__col--${size}`);
    }
  });

  it("renders with semantic HTML tags", () => {
    const semanticTags = [
      "article",
      "aside",
      "section",
      "header",
      "footer",
      "main",
      "nav",
    ];

    semanticTags.forEach((tag) => {
      const { container } = render(<GridCol tag={tag} size={6} />);
      const element = container.querySelector(tag);
      expect(element).toBeTruthy();
      expect(element).toHaveClass("grid__col--6");
    });
  });

  it("renders with form elements as tags", () => {
    const { container } = render(<GridCol tag="label" size="auto" />);
    const label = container.querySelector("label");
    expect(label).toBeTruthy();
    expect(label).toHaveClass("grid__col--auto");
  });

  it("combines size and alignment props correctly", () => {
    const { getByTestId } = render(
      <GridCol
        data-testid="test-id"
        size={8}
        align="top"
        className="custom-class"
      />,
    );
    const el = getByTestId("test-id");
    expect(el).toHaveClass("grid__col--8", "align-self-top", "custom-class");
  });

  it("renders with complex content and styling", () => {
    const { getByText } = render(
      <GridCol size="fill" align="middle" className="content-col">
        <h2>Title</h2>
        <p>Paragraph content</p>
        <button>Click me</button>
      </GridCol>,
    );

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

  it("renders multiple GridCols with different configurations", () => {
    const { container } = render(
      <div>
        <GridCol size={4} align="top" className="col-1">
          Column 1
        </GridCol>
        <GridCol size="auto" align="middle" className="col-2">
          Column 2
        </GridCol>
        <GridCol size="fill" align="bottom" className="col-3">
          Column 3
        </GridCol>
        <GridCol size="shrink" align="stretch" className="col-4">
          Column 4
        </GridCol>
      </div>,
    );

    const cols = container.querySelectorAll(".grid__col");
    expect(cols).toHaveLength(4);

    expect(cols[0]).toHaveClass("grid__col--4", "align-self-top", "col-1");
    expect(cols[1]).toHaveClass(
      "grid__col--auto",
      "align-self-middle",
      "col-2",
    );
    expect(cols[2]).toHaveClass(
      "grid__col--fill",
      "align-self-bottom",
      "col-3",
    );
    expect(cols[3]).toHaveClass(
      "grid__col--shrink",
      "align-self-stretch",
      "col-4",
    );
  });

  it("renders with inline styles and data attributes", () => {
    const { getByTestId } = render(
      <GridCol
        data-testid="test-id"
        size={6}
        data-component="grid-col"
        data-size="6"
      />,
    );

    const el = getByTestId("test-id");
    expect(el).toHaveAttribute("data-component", "grid-col");
    expect(el).toHaveAttribute("data-size", "6");
  });

  it("renders with event handlers", () => {
    const handleClick = vi.fn();
    const { getByTestId } = render(
      <GridCol
        data-testid="test-id"
        size={3}
        onClick={handleClick}
        onMouseEnter={() => {}}
      />,
    );

    const el = getByTestId("test-id");
    el.click();
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it("renders with aria attributes for accessibility", () => {
    const { getByTestId } = render(
      <GridCol
        data-testid="test-id"
        size="auto"
        role="region"
        aria-label="Content section"
        aria-describedby="description"
      />,
    );

    const el = getByTestId("test-id");
    expect(el).toHaveAttribute("role", "region");
    expect(el).toHaveAttribute("aria-label", "Content section");
    expect(el).toHaveAttribute("aria-describedby", "description");
  });
});
