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

describe("ErrorInfo", () => {

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

  test("renders with default props", () => {
    render(<ErrorInfo />);

    const alert = screen.getByRole("alert");
    assert.notStrictEqual(alert, null);
    assert.ok(alert.classList.contains("errorInfo"));
  });

  test("renders string error message", () => {
    render(<ErrorInfo error={"Custom error message"} />);

    const alert = screen.getByRole("alert");
    assert.strictEqual(alert.textContent, "Custom error message");
  });

  test("renders Error instance message", () => {
    const error = new Error("Something went wrong");
    render(<ErrorInfo error={error} />);

    const alert = screen.getByRole("alert");
    assert.strictEqual(alert.textContent, "Something went wrong");
  });

  test("renders Error instance with toString when message is empty", () => {
    const error = new Error();
    error.message = "";
    render(<ErrorInfo error={error} />);

    const alert = screen.getByRole("alert");
    assert.notStrictEqual(alert, null);
    assert.ok(alert.textContent);
  });

  test("renders array of string errors", () => {
    const errors = [ "Error 1", "Error 2", "Error 3" ];
    render(<ErrorInfo error={errors} />);

    const alert = screen.getByRole("alert");
    assert.strictEqual(alert.textContent, "Error 1\nError 2\nError 3");
  });

  test("renders array of Error instances", () => {
    const errors = [
      new Error("First error"),
      new Error("Second error"),
      new Error("Third error"),
    ];
    render(<ErrorInfo error={errors} />);

    const alert = screen.getByRole("alert");
    assert.strictEqual(alert.textContent, "First error\nSecond error\nThird error");
  });

  test("renders mixed array of strings and Error instances", () => {
    const errors = [
      "String error",
      new Error("Error instance"),
      "Another string",
    ];
    render(<ErrorInfo error={errors} />);

    const alert = screen.getByRole("alert");
    assert.strictEqual(alert.textContent, "String error\nError instance\nAnother string");
  });

  test("renders custom children instead of error", () => {
    render(
      <ErrorInfo error={"This should not show"}>
        <div data-testid={"custom-content"}>Custom error content</div>
      </ErrorInfo>
    );

    assert.notStrictEqual(screen.queryByTestId("custom-content"), null);
    assert.strictEqual(screen.queryByText("This should not show"), null);
  });

  test("passes extra HTML attributes", () => {
    render(
      <ErrorInfo
        extraAttrs={{
          "data-testid": "error-component",
          "aria-live": "polite",
          id: "error-1",
        }}
      />
    );

    const alert = screen.getByTestId("error-component");
    assert.strictEqual(alert.getAttribute("aria-live"), "polite");
    assert.strictEqual(alert.getAttribute("id"), "error-1");
  });

  test("handles array with Error instances without messages", () => {
    const errors = [ new Error(), new Error() ];
    errors[0].message = "";
    errors[1].message = "";

    render(<ErrorInfo error={errors} />);

    const alert = screen.getByRole("alert");
    assert.notStrictEqual(alert, null);
  });
});
