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

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

  /* COMMON */

  test("renders without crashing", () => {
    render(<FormattedValue value={0} />);
    const element = document.querySelector(".formattedValue");
    assert.notStrictEqual(element, null);
  });

  test("applies extra classes with prefix", () => {
    render(
      <FormattedValue
        value={0}
        extraClasses={{ large: true, bold: true }}
      />
    );

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

  test("passes extra attributes", () => {
    render(
      <FormattedValue
        value={0}
        extraAttrs={{
          "data-testid": "formatted-value",
          "aria-label": "Formatted number",
        }}
      />
    );

    const element = screen.getByTestId("formatted-value");
    assert.strictEqual(element.getAttribute("aria-label"), "Formatted number");
  });

  /* TAG PROP */

  test("renders with custom tag", () => {
    render(<FormattedValue value={0} tag={"span"} />);
    const element = document.querySelector("span.formattedValue");
    assert.notStrictEqual(element, null);
  });

  /* VALUE FORMATTING */

  test("formats numbers correctly", () => {
    render(
      <>
        <FormattedValue value={1234567} />
        <FormattedValue value={1234567} separator={","} />
        <FormattedValue value={1234.56} />
      </>
    );

    const values = document.querySelectorAll(".formattedValue__value");
    assert.strictEqual(values[0]?.textContent, "1 234 567");
    assert.strictEqual(values[1]?.textContent, "1,234,567");
    assert.strictEqual(values[2]?.textContent, "1 234.56");
  });

  test("handles string values", () => {
    render(
      <>
        <FormattedValue value={"1234567"} />
        <FormattedValue value={"1 234 567"} />
      </>
    );

    const values = document.querySelectorAll(".formattedValue__value");
    assert.strictEqual(values[0]?.textContent, "1 234 567");
    assert.strictEqual(values[1]?.textContent, "1 234 567");
  });

  /* PREFIX AND POSTFIX */

  test("renders with prefix and postfix", () => {
    render(<FormattedValue value={1000} prefix={"$"} postfix={"USD"} />);

    assert.strictEqual(document.querySelector(".formattedValue__prefix")?.textContent, "$");
    assert.strictEqual(document.querySelector(".formattedValue__value")?.textContent, "1 000");
    assert.strictEqual(document.querySelector(".formattedValue__postfix")?.textContent, "USD");
  });

  /* CHILDREN */

  test("renders children instead of formatted value", () => {
    render(
      <FormattedValue value={1000}>
        <span data-testid={"custom"}>Custom</span>
      </FormattedValue>
    );

    assert.notStrictEqual(screen.getByTestId("custom"), null);
    assert.strictEqual(document.querySelector(".formattedValue__value"), null);
  });

  /* EDGE CASES */

  test("handles edge values", () => {
    render(
      <>
        <FormattedValue value={0} />
        <FormattedValue value={-1000} />
        <FormattedValue value={""} />
        <FormattedValue value={"abc"} />
      </>
    );

    const values = document.querySelectorAll(".formattedValue__value");
    const texts = Array.from(values).map((el) => el.textContent);

    assert.strictEqual(texts.includes("0"), true);
    assert.strictEqual(texts.includes("-1 000"), true);
    assert.strictEqual(texts.includes(""), true);
    assert.strictEqual(texts.includes("abc"), true);
  });

  /* STRUCTURE */

  test("renders with correct structure", () => {
    render(<FormattedValue value={1000} prefix={"$"} postfix={"USD"} />);

    const container = document.querySelector(".formattedValue");
    assert.strictEqual(container?.children.length, 3);
    assert.notStrictEqual(document.querySelector(".formattedValue__prefix"), null);
    assert.notStrictEqual(document.querySelector(".formattedValue__value"), null);
    assert.notStrictEqual(document.querySelector(".formattedValue__postfix"), null);
  });

  test("does not render prefix/postfix when not provided", () => {
    render(<FormattedValue value={1000} />);

    assert.strictEqual(document.querySelector(".formattedValue__prefix"), null);
    assert.strictEqual(document.querySelector(".formattedValue__postfix"), null);
    assert.strictEqual(document.querySelector(".formattedValue")?.children.length, 1);
  });
});