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

import { PaymentPlan, PaymentPlanSchema } from "@/data/schemas/payment";
import { behaviorAnalytics } from "@/lib/analytics";

import { usePaymentPlanAnalytics } from "../use-payment-plan-analytics";

const firstPlan = PaymentPlanSchema.parse({
  planId: "plan-1",
  planName: "Plan One",
  orderType: "dol",
  vipDays: null,
  dolAmount: 100,
  creditBalance: 100,
  amountCents: 499,
  originalAmountCents: null,
  currency: "USD",
});
const secondPlan = PaymentPlanSchema.parse({
  planId: "plan-2",
  planName: "Plan Two",
  orderType: "dol",
  vipDays: null,
  dolAmount: 250,
  creditBalance: 250,
  amountCents: 999,
  originalAmountCents: null,
  currency: "USD",
});

function Harness({ plans }: { plans: readonly PaymentPlan[] }) {
  usePaymentPlanAnalytics(plans, {
    entryPoint: "subscription_direct",
    triggerReason: "manual_recharge",
  });
  return null;
}

describe("usePaymentPlanAnalytics", () => {
  let container: HTMLDivElement;
  let root: Root;

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

  afterEach(() => {
    act(() => root.unmount());
    container.remove();
    vi.restoreAllMocks();
  });

  it("tracks displayed order once per plan during a page mount", () => {
    const impression = vi
      .spyOn(behaviorAnalytics, "planImpression")
      .mockImplementation(() => undefined);

    act(() => root.render(<Harness plans={[firstPlan]} />));
    act(() => root.render(<Harness plans={[firstPlan, secondPlan]} />));
    act(() => root.render(<Harness plans={[firstPlan, secondPlan]} />));

    expect(impression).toHaveBeenCalledTimes(2);
    expect(impression).toHaveBeenNthCalledWith(
      1,
      firstPlan,
      1,
      expect.any(Object),
    );
    expect(impression).toHaveBeenNthCalledWith(
      2,
      secondPlan,
      2,
      expect.any(Object),
    );
  });
});
