import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen } from "@testing-library/react";
import { PostHogWrapper } from "#/components/providers/posthog-wrapper";
import OptionService from "#/api/option-service/option-service.api";

// Mock PostHogProvider to capture the options passed to it
const mockPostHogProvider = vi.fn();
vi.mock("posthog-js/react", () => ({
  PostHogProvider: (props: Record<string, unknown>) => {
    mockPostHogProvider(props);
    return props.children;
  },
}));

describe("PostHogWrapper", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    // Reset URL hash
    window.location.hash = "";
    // Clear sessionStorage
    sessionStorage.clear();
    // Mock the config fetch
    // @ts-expect-error - partial mock
    vi.spyOn(OptionService, "getConfig").mockResolvedValue({
      posthog_client_key: "test-posthog-key",
    });
  });

  it("should initialize PostHog with bootstrap IDs from URL hash (without ph_ prefix)", async () => {
    // Webflow sends distinct_id and session_id without the ph_ prefix
    window.location.hash = "distinct_id=user-123&session_id=session-456";

    render(
      <PostHogWrapper>
        <div data-testid="child" />
      </PostHogWrapper>,
    );

    await screen.findByTestId("child");

    expect(mockPostHogProvider).toHaveBeenCalledWith(
      expect.objectContaining({
        options: expect.objectContaining({
          bootstrap: {
            distinctID: "user-123",
            sessionID: "session-456",
          },
        }),
      }),
    );
  });

  it("should clean up URL hash after extracting bootstrap IDs", async () => {
    window.location.hash = "distinct_id=user-123&session_id=session-456";

    render(
      <PostHogWrapper>
        <div data-testid="child" />
      </PostHogWrapper>,
    );

    await screen.findByTestId("child");

    expect(window.location.hash).toBe("");
  });

  it("should persist bootstrap IDs to sessionStorage for OAuth survival", async () => {
    window.location.hash = "distinct_id=user-123&session_id=session-456";

    render(
      <PostHogWrapper>
        <div data-testid="child" />
      </PostHogWrapper>,
    );

    await screen.findByTestId("child");

    // After extracting from hash, IDs should NOT remain in sessionStorage
    // because they were already consumed during this page load.
    // But if a full-page redirect happened before PostHog init,
    // sessionStorage would still have them for the next load.
    // We verify the write happened by checking the provider received the IDs.
    expect(mockPostHogProvider).toHaveBeenCalledWith(
      expect.objectContaining({
        options: expect.objectContaining({
          bootstrap: {
            distinctID: "user-123",
            sessionID: "session-456",
          },
        }),
      }),
    );
  });

  it("should read bootstrap IDs from sessionStorage when hash is absent (post-OAuth)", async () => {
    // Simulate returning from OAuth: no hash, but sessionStorage has the IDs
    sessionStorage.setItem(
      "posthog_bootstrap",
      JSON.stringify({ distinctID: "user-123", sessionID: "session-456" }),
    );

    render(
      <PostHogWrapper>
        <div data-testid="child" />
      </PostHogWrapper>,
    );

    await screen.findByTestId("child");

    expect(mockPostHogProvider).toHaveBeenCalledWith(
      expect.objectContaining({
        options: expect.objectContaining({
          bootstrap: {
            distinctID: "user-123",
            sessionID: "session-456",
          },
        }),
      }),
    );
  });

  it("should clean up sessionStorage after consuming bootstrap IDs", async () => {
    sessionStorage.setItem(
      "posthog_bootstrap",
      JSON.stringify({ distinctID: "user-123", sessionID: "session-456" }),
    );

    render(
      <PostHogWrapper>
        <div data-testid="child" />
      </PostHogWrapper>,
    );

    await screen.findByTestId("child");

    expect(sessionStorage.getItem("posthog_bootstrap")).toBeNull();
  });

  it("should initialize PostHog with health monitoring config (web vitals, error tracking, network timing)", async () => {
    render(
      <PostHogWrapper>
        <div data-testid="child" />
      </PostHogWrapper>,
    );

    await screen.findByTestId("child");

    expect(mockPostHogProvider).toHaveBeenCalledWith(
      expect.objectContaining({
        options: expect.objectContaining({
          capture_performance: {
            network_timing: true,
            web_vitals: true,
          },
          capture_exceptions: true,
        }),
      }),
    );
  });

  it("should initialize without bootstrap when neither hash nor sessionStorage has IDs", async () => {
    render(
      <PostHogWrapper>
        <div data-testid="child" />
      </PostHogWrapper>,
    );

    await screen.findByTestId("child");

    expect(mockPostHogProvider).toHaveBeenCalledWith(
      expect.objectContaining({
        options: expect.objectContaining({
          bootstrap: undefined,
        }),
      }),
    );
  });
});
