import { render, screen, cleanup } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import assert from "node:assert";
import {
  describe, test, mock, afterEach,
} from "node:test";
import { Btn } from "./index";

describe("Btn", () => {

  afterEach(() => {
    cleanup();
  });

  /* COMMON */

  test("renders without crashing", () => {
    render(<Btn />);
    assert.notStrictEqual(screen.queryByRole("button"), null);
  });

  test("renders label text", () => {
    render(<Btn label={"Сохранить"} />);
    assert.notStrictEqual(screen.queryByText("Сохранить"), null);
  });

  test("calls onClick when clicked", async () => {
    const onClick = mock.fn();
    const user = userEvent.setup();

    render(<Btn onClick={onClick} />);

    await user.click(screen.getByRole("button"));

    assert.strictEqual(onClick.mock.calls.length, 1);
  });

  test("does not call onClick when disabled", async () => {
    const onClick = mock.fn();
    const user = userEvent.setup();

    render(<Btn isDisabled onClick={onClick} />);
    await user.click(screen.getByRole("button"));

    assert.strictEqual(onClick.mock.calls.length, 0);
    const button = screen.getByRole("button");
    assert.strictEqual(button.hasAttribute("disabled"), true);
  });

  test("passes id and form attributes", () => {
    render(<Btn id={"my-btn"} form={"my-form"} />);
    const button = screen.getByRole("button");
    assert.strictEqual(button.getAttribute("id"), "my-btn");
    assert.strictEqual(button.getAttribute("form"), "my-form");
  });

  /* LINK */

  test("renders as link when type='link'", () => {
    render(<Btn type={"link"} href={"/test"} />);
    const element = screen.getByRole("link");
    assert.strictEqual(element.tagName, "A");
  });

  test("passes href and target to link", () => {
    render(
      <Btn
        type={"link"}
        href={"https://example.com"}
        target={"_blank"}
      />
    );

    const link = screen.getByRole("link");
    assert.strictEqual(link.getAttribute("href"), "https://example.com");
    assert.strictEqual(link.getAttribute("target"), "_blank");
  });

  test("prevents click and navigation for disabled link", async () => {
    const user = userEvent.setup();
    const onClick = mock.fn();

    render(
      <Btn
        type={"link"}
        href={"https://example.com"}
        isDisabled={true}
        onClick={onClick}
      />
    );

    const link = document.querySelector<HTMLAnchorElement>("a");
    assert.ok(link);
    await user.click(link);

    assert.strictEqual(onClick.mock.calls.length, 0);
    assert.strictEqual(link.getAttribute("href"), null);
    assert.strictEqual(link.getAttribute("aria-disabled"), "true");
    assert.strictEqual(link.getAttribute("tabindex"), "-1");
  });

  test("sets aria-label from title for icon-only button", () => {
    render(<Btn icon={"remove"} label={null} title={"Delete item"} />);
    const button = screen.getByRole("button");
    assert.strictEqual(button.getAttribute("aria-label"), "Delete item");
  });

  /* ICON */

  test("renders icon when icon prop is provided", () => {
    render(<Btn icon={"test-icon"} />);
    assert.notStrictEqual(screen.queryByTestId("btn-icon"), null);
  });

  /* CHILDREN */

  test("renders children instead of label and icon", () => {
    render(
      <Btn label={"Label"}>
        <span>Custom content</span>
      </Btn>
    );

    assert.notStrictEqual(screen.queryByText("Custom content"), null);
    assert.strictEqual(screen.queryByText("Label"), null);
  });
});
