import { render, screen, cleanup } from "@testing-library/react";
import assert from "node:assert";
import { describe, test, afterEach } from "node:test";
import { Grid, GridItem } from "./index";

describe("Grid", () => {
  afterEach(() => {
    cleanup();
  });

  /* COMMON */

  test("renders without crashing", () => {
    render(<Grid />);
    assert.notStrictEqual(document.querySelector(".grid"), null);
  });

  test("applies classes", () => {
    render(
      <Grid
        type={"grid"}
        extraClasses={{ large: true }}
      />
    );

    const element = document.querySelector(".grid");
    assert.strictEqual(element?.classList.contains("grid--isGrid"), true);
    assert.strictEqual(element?.classList.contains("grid--large"), true);
  });

  test("passes extra attributes", () => {
    render(
      <Grid
        extraAttrs={{ "data-testid": "grid" }}
      />
    );

    assert.notStrictEqual(screen.getByTestId("grid"), null);
  });

  /* TAG PROP */

  test("renders with custom tag", () => {
    render(<Grid tag={"ul"} />);
    assert.notStrictEqual(document.querySelector("ul.grid"), null);
  });

  /* COLUMNS */

  test("sets columns CSS variables", () => {
    const { rerender } = render(<Grid columns={[ 4, 3, 2 ]} />);

    let element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsDesktop"), "4");
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsTablet"), "3");
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsMobile"), "2");

    rerender(<Grid columns={2} />);
    element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsDesktop"), "2");
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsTablet"), "2");
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsMobile"), "1");

    rerender(<Grid columns={"auto"} />);
    element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsDesktop"), "auto");
  });

  /* GAPS */

  test("sets gaps CSS variables", () => {
    const { rerender } = render(<Grid gaps={[ "2rem", "1rem", "0.5rem" ]} />);

    let element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridGapDesktop"), "2rem");
    assert.strictEqual(element.style.getPropertyValue("--gridGapTablet"), "1rem");
    assert.strictEqual(element.style.getPropertyValue("--gridGapMobile"), "0.5rem");

    rerender(<Grid gaps={"1rem"} />);
    element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridGapDesktop"), "1rem");
  });

  /* ALIGN & JUSTIFY */

  test("sets align and justify CSS variables", () => {
    const { rerender } = render(<Grid align={[ "center", "start", "end" ]} />);

    let element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridAlignItemsDesktop"), "center");
    assert.strictEqual(element.style.getPropertyValue("--gridAlignItemsTablet"), "start");
    assert.strictEqual(element.style.getPropertyValue("--gridAlignItemsMobile"), "end");

    rerender(<Grid align={"center"} />);
    element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridAlignItemsDesktop"), "center");

    rerender(<Grid justify={[ "center", "space-between", "end" ]} />);
    element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridJustifyContentDesktop"), "center");
    assert.strictEqual(element.style.getPropertyValue("--gridJustifyContentTablet"), "space-between");
    assert.strictEqual(element.style.getPropertyValue("--gridJustifyContentMobile"), "end");
  });

  /* STYLES */

  test("merges custom styles", () => {
    render(
      <Grid
        columns={4}
        style={{ backgroundColor: "red" }}
      />
    );

    const element = document.querySelector(".grid") as HTMLElement;
    assert.strictEqual(element.style.getPropertyValue("--gridColumnsDesktop"), "4");
    assert.strictEqual(element.style.backgroundColor, "red");
  });

  /* CHILDREN */

  test("renders children", () => {
    render(
      <Grid>
        <div data-testid={"child"}>Child</div>
      </Grid>
    );

    assert.notStrictEqual(screen.getByTestId("child"), null);
  });

  /* GRID ITEM */

  test("renders GridItem with correct tag", () => {
    // Первый случай: Grid с tag="ul"
    render(
      <Grid tag={"ul"}>
        <GridItem extraAttrs={{ "data-testid": "item" }}>Item</GridItem>
      </Grid>
    );

    const item1 = screen.getByTestId("item");
    assert.strictEqual(item1.tagName.toLowerCase(), "li");

    // Очищаем и рендерим второй случай
    cleanup();

    // Второй случай: Grid с tag="div"
    render(
      <Grid tag={"div"}>
        <GridItem extraAttrs={{ "data-testid": "item" }}>Item</GridItem>
      </Grid>
    );

    const item2 = screen.getByTestId("item");
    assert.strictEqual(item2.tagName.toLowerCase(), "div");
  });

  test("GridItem applies classes and styles", () => {
    render(
      <Grid>
        <GridItem
          extraClasses={{ large: true }}
          utilClasses={[ "first" ]}
          align={"center"}
          justify={"end"}
          style={{ color: "red" }}
          extraAttrs={{ "data-testid": "item" }}
        >
          Item
        </GridItem>
      </Grid>
    );

    const item = screen.getByTestId("item") as HTMLElement;

    // Проверяем классы
    assert.strictEqual(item.classList.contains("grid__item--large"), true);
    assert.strictEqual(item.classList.contains("first"), true);

    // Проверяем стили
    assert.strictEqual(item.style.getPropertyValue("--gridItemAlignSelf"), "center");
    assert.strictEqual(item.style.getPropertyValue("--gridItemJustifySelf"), "end");
    assert.strictEqual(item.style.color, "red");
  });

  /* EDGE CASES */

  test("handles no props", () => {
    render(<Grid />);
    assert.notStrictEqual(document.querySelector(".grid"), null);
  });
});