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

import { PaymentLaunchDialogs } from "../payment-launch-dialogs";

const hiddenLaunch = {
  handleEzpayCancel: vi.fn(),
  handleEzpayConfirm: vi.fn(),
  handleQrisClose: vi.fn(),
  handleStripeClose: vi.fn(),
  handleStripeConfirmed: vi.fn(),
  isConfirmingEzpay: false,
  qrisErrorMessage: null,
  qrisPayment: null,
  qrisStatus: null,
  shouldShowEzpayConfirmDialog: false,
  shouldShowQrisDialog: false,
  shouldShowStripeDialog: false,
  stripeClientSecret: null,
  stripeCustomerSessionClientSecret: null,
  savedPaymentMethodsEnabled: false,
};

describe("PaymentLaunchDialogs", () => {
  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("renders nothing when neither payment dialog is active", () => {
    act(() =>
      root.render(
        <PaymentLaunchDialogs
          currentOrderId={null}
          externalCheckoutAnalyticsKey="payment.external_checkout"
          ezpayDescription="Continue to payment."
          launch={hiddenLaunch}
        />,
      ),
    );

    expect(document.body.querySelector('[role="dialog"]')).toBeNull();
    expect(document.body.querySelector('[role="alertdialog"]')).toBeNull();
  });

  it("portals the shared Ezpay confirmation outside transformed checkout UI", () => {
    act(() =>
      root.render(
        <PaymentLaunchDialogs
          currentOrderId="order-123"
          externalCheckoutAnalyticsKey="tip.external_checkout"
          ezpayDescription="Your coffee order is ready."
          launch={{
            ...hiddenLaunch,
            isConfirmingEzpay: true,
            shouldShowEzpayConfirmDialog: true,
          }}
        />,
      ),
    );

    const dialog = document.body.querySelector('[role="alertdialog"]');
    expect(dialog).not.toBeNull();
    expect(container.contains(dialog)).toBe(false);
    expect(dialog?.parentElement?.parentElement).toBe(document.body);
    expect(dialog?.textContent).toContain("Continue to payment?");
    expect(dialog?.textContent).toContain("Your coffee order is ready.");
    expect(dialog?.textContent).toContain("Order No. order-123");
    expect(
      dialog?.querySelector("button[data-analytics-key]")?.getAttribute(
        "data-analytics-key",
      ),
    ).toBe("tip.external_checkout");
    expect(dialog?.textContent).toContain("Opening...");
    expect(document.body.style.overflow).toBe("hidden");
  });

  it("portals an accessible QRIS dialog with display cents and order status", () => {
    act(() =>
      root.render(
        <PaymentLaunchDialogs
          currentOrderId="order-id-qris"
          externalCheckoutAnalyticsKey="tip.external_checkout"
          ezpayDescription="Scan QRIS to finish the payment."
          launch={{
            ...hiddenLaunch,
            qrisPayment: {
              qrData: "00020101021226670016COM.NOBUBANK.WWW",
              orderId: "order-id-qris",
              amountCents: 5_000_000,
              currency: "IDR",
            },
            qrisStatus: "pending",
            shouldShowQrisDialog: true,
          }}
        />,
      ),
    );

    const dialog = document.body.querySelector('[role="dialog"]');
    expect(dialog).not.toBeNull();
    expect(container.contains(dialog)).toBe(false);
    expect(dialog?.textContent).toContain("Scan to pay with QRIS");
    expect(dialog?.querySelector("svg title")?.textContent).toBe(
      "QRIS payment QR code",
    );
    expect(dialog?.textContent).toContain("Order No. order-id-qris");
    expect(dialog?.textContent).toContain("Rp");
    expect(dialog?.textContent).toContain("50.000");
    expect(dialog?.textContent).toContain("Waiting for payment");
  });

  it("shows QRIS failure state and handles empty QR data safely", () => {
    act(() =>
      root.render(
        <PaymentLaunchDialogs
          currentOrderId="order-id-qris"
          externalCheckoutAnalyticsKey="payment.external_checkout"
          ezpayDescription="Scan QRIS to finish the payment."
          launch={{
            ...hiddenLaunch,
            qrisErrorMessage: "Payment failed or was cancelled.",
            qrisPayment: {
              qrData: "",
              orderId: "order-id-qris",
              amountCents: 5_000_000,
              currency: "IDR",
            },
            qrisStatus: "failed",
            shouldShowQrisDialog: true,
          }}
        />,
      ),
    );

    const dialog = document.body.querySelector('[role="dialog"]');
    expect(dialog?.textContent).toContain("QRIS data is unavailable");
    expect(dialog?.textContent).toContain("Payment failed or was cancelled.");
    expect(dialog?.textContent).toContain("Close");
  });
});
