import { createRef } from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Link } from ".";

const CLASS_NAME = "mobius-link";

describe("Test for Link", () => {
  it("should render without errors", () => {
    render(<Link href="#test">Test</Link>);
  });

  it("should call the onClick", async () => {
    const onClick = vi.fn();
    render(
      <Link href="#test" onClick={onClick}>
        Click
      </Link>,
    );
    await userEvent.click(screen.getByText("Click"));
    expect(onClick).toHaveBeenCalled();
  });

  it("uses the elementType prop", () => {
    function CustomComponent(props: any) {
      return <a data-testid="custom-component" {...props} />;
    }
    render(
      <Link href="#test" elementType={CustomComponent}>
        Test
      </Link>,
    );
    expect(screen.getByTestId("custom-component")).toBeInTheDocument();
  });

  describe("given elementType", () => {
    it("is not applied as element attribute", () => {
      const { container } = render(
        <Link href="#test" elementType="ul">
          Test
        </Link>,
      );
      expect(container.firstChild).not.toHaveAttribute("elementtype", "ul");
    });
  });

  describe("when disabled", () => {
    it("has aria-disabled attribute", () => {
      render(
        <Link href="#" isDisabled>
          Click
        </Link>,
      );
      expect(screen.getByRole("link")).toHaveAttribute("aria-disabled", "true");
    });
  });

  describe("focus", () => {
    it("is focusable via Tab", async () => {
      render(<Link href="#">Click</Link>);
      await userEvent.tab();
      expect(screen.getByRole("link")).toHaveFocus();
    });
  });

  describe("uses correct class names", () => {
    it("uses Mobius class", () => {
      render(
        <Link href="#test" data-testid="test">
          Sample text
        </Link>,
      );
      expect(screen.getByTestId("test")).toHaveClass("mobius");
    });

    it("uses base Mobius class", () => {
      render(
        <Link href="#test" data-testid="test">
          Sample text
        </Link>,
      );
      expect(screen.getByTestId("test")).toHaveClass(CLASS_NAME);
    });

    it("includes custom class name", () => {
      render(
        <Link href="#test" className="my-class" data-testid="test">
          Sample Text
        </Link>,
      );
      expect(screen.getByTestId("test")).toHaveClass("my-class");
      expect(screen.getByTestId("test")).toHaveClass(CLASS_NAME);
    });

    it("includes the disabled class name", async () => {
      render(
        <Link href="#test" data-testid="test" isDisabled>
          Sample text
        </Link>,
      );
      await userEvent.tab();
      expect(screen.getByTestId("test")).toHaveClass("--is-disabled");
    });

    it.each(["primary", "secondary"] as const)(
      "applies mobius-link--%s class",
      variant => {
        render(
          <Link href="#test" data-testid="test" variant={variant}>
            Sample text
          </Link>,
        );
        expect(screen.getByTestId("test")).toHaveClass(
          `mobius-link--${variant}`,
        );
      },
    );
  });

  describe("given the the link has disabled prop", () => {
    it("does not pass the prop as an attribute", async () => {
      render(
        <Link href="#test" data-testid="test" isDisabled>
          Sample text
        </Link>,
      );
      await userEvent.tab();
      expect(screen.getByTestId("test")).toBeEnabled();
    });
  });

  it("forwards ref", () => {
    const ref = createRef<HTMLAnchorElement>();
    render(
      <Link ref={ref} href="#">
        Text
      </Link>,
    );
    expect(ref.current).toBeInstanceOf(HTMLAnchorElement);
  });
});
