import { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

import { StripePaymentDialogLoading } from "../lazy-stripe-payment-dialog";
import { StripePaymentDialog } from "../stripe-payment-dialog";

describe("Stripe payment portal states", () => {
  let container: HTMLDivElement;
  let root: Root;

  beforeEach(() => {
    (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean })
      .IS_REACT_ACT_ENVIRONMENT = true;
    container = document.createElement("div");
    container.style.transform = "translateX(50%)";
    document.body.appendChild(container);
    root = createRoot(container);
  });

  afterEach(() => {
    act(() => root.unmount());
    container.remove();
    document.body.style.overflow = "";
  });

  it("portals the unavailable state and keeps its explicit close action", () => {
    const onClose = vi.fn();

    act(() =>
      root.render(
        <StripePaymentDialog
          clientSecret="client-secret"
          onClose={onClose}
        />,
      ),
    );

    const dialog = document.body.querySelector('[role="alertdialog"]');
    expect(dialog).not.toBeNull();
    expect(container.contains(dialog)).toBe(false);
    expect(dialog?.textContent).toContain("Payment unavailable");
    expect(dialog?.getAttribute("aria-labelledby")).toBeTruthy();
    expect(dialog?.getAttribute("aria-describedby")).toBeTruthy();

    const okButton = Array.from(dialog?.querySelectorAll("button") ?? []).find(
      (button) => button.textContent === "OK",
    );
    act(() => okButton?.dispatchEvent(new MouseEvent("click", { bubbles: true })));
    expect(onClose).toHaveBeenCalledOnce();
  });

  it("portals the lazy loading state", () => {
    act(() => root.render(<StripePaymentDialogLoading />));

    const dialog = document.body.querySelector('[role="dialog"]');
    expect(dialog).not.toBeNull();
    expect(container.contains(dialog)).toBe(false);
    expect(dialog?.textContent).toContain("Preparing secure payment");
    expect(dialog?.textContent).toContain("Loading payment methods...");
    expect(dialog?.querySelector('[aria-busy="true"]')).not.toBeNull();
  });
});
