import { render } from "@solidjs/testing-library";
import { createSignal } from "solid-js";
import { describe, expect, it } from "vitest";
import { Presence } from "../../src/utilities/presence/presence";

describe("Presence", () => {
  it("renders children when present is true", () => {
    const { getByTestId } = render(() => (
      <Presence present={true}>
        <div data-testid="content">hello</div>
      </Presence>
    ));
    expect(getByTestId("content")).toBeTruthy();
  });

  it("does not render children when present is false", () => {
    const { queryByTestId } = render(() => (
      <Presence present={false}>
        <div data-testid="content">hello</div>
      </Presence>
    ));
    expect(queryByTestId("content")).toBeNull();
  });

  it("mounts children when present transitions false→true", async () => {
    const [present, setPresent] = createSignal(false);
    const { queryByTestId } = render(() => (
      <Presence present={present()}>
        <div data-testid="content">hello</div>
      </Presence>
    ));
    expect(queryByTestId("content")).toBeNull();
    setPresent(true);
    await Promise.resolve();
    expect(queryByTestId("content")).toBeTruthy();
  });

  it("unmounts children when present transitions true→false", async () => {
    const [present, setPresent] = createSignal(true);
    const { queryByTestId } = render(() => (
      <Presence present={present()}>
        <div data-testid="content">hello</div>
      </Presence>
    ));
    expect(queryByTestId("content")).toBeTruthy();
    setPresent(false);
    await Promise.resolve();
    expect(queryByTestId("content")).toBeNull();
  });

  it("keeps children mounted with forceMount when present is false", () => {
    const { getByTestId } = render(() => (
      <Presence present={false} forceMount>
        <div data-testid="content">hello</div>
      </Presence>
    ));
    expect(getByTestId("content")).toBeTruthy();
  });

  it("exposes opening signal via children-as-function", async () => {
    const [present, setPresent] = createSignal(false);
    let capturedOpening = false;

    render(() => (
      <Presence present={present()}>
        {({ opening }) => {
          if (opening()) capturedOpening = true;
          return <div data-testid="content">hello</div>;
        }}
      </Presence>
    ));

    setPresent(true);
    // opening is true for one microtask after transitioning in
    await Promise.resolve();
    expect(capturedOpening).toBe(true);
  });

  it("exposes closing signal via children-as-function", async () => {
    const [present, setPresent] = createSignal(true);
    let capturedClosing = false;

    render(() => (
      <Presence present={present()} forceMount>
        {({ closing }) => {
          if (closing()) capturedClosing = true;
          return <div data-testid="content">hello</div>;
        }}
      </Presence>
    ));

    setPresent(false);
    await Promise.resolve();
    expect(capturedClosing).toBe(true);
  });
});
