import { beforeEach, describe, expect, it, vi } from "vitest";
import { render, waitFor } from "@testing-library/react";
import FcmAuthWarmup from "@/components/auth/FcmAuthWarmup";

const { warmupFcmForAuth, mockAuthState } = vi.hoisted(() => ({
  warmupFcmForAuth: vi.fn(),
  mockAuthState: {
    pendingLogin: null as {
      email: string;
      password?: string;
      device_id?: string;
    } | null,
    setPendingLogin: vi.fn(),
  },
}));

vi.mock("@/lib/firebase/messaging", () => ({
  warmupFcmForAuth,
}));

vi.mock("@/lib/auth/store", () => ({
  useAuthStore: Object.assign(
    (selector: (state: typeof mockAuthState) => unknown) =>
      selector(mockAuthState),
    {
      getState: () => mockAuthState,
    },
  ),
}));

describe("FcmAuthWarmup", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    sessionStorage.clear();
    mockAuthState.pendingLogin = null;
  });

  it("requests permission and stores device_id for pending login on mount", async () => {
    mockAuthState.pendingLogin = {
      email: "user@example.com",
      password: "secret",
    };
    warmupFcmForAuth.mockResolvedValueOnce({
      token: "warm-token",
      reason: null,
    });

    render(<FcmAuthWarmup />);

    await waitFor(() => {
      expect(warmupFcmForAuth).toHaveBeenCalledTimes(1);
    });
    expect(mockAuthState.setPendingLogin).toHaveBeenCalledWith({
      email: "user@example.com",
      password: "secret",
      device_id: "warm-token",
    });
    expect(sessionStorage.getItem("bb_fcm_device_id")).toBe("warm-token");
  });

  it("reuses session device_id without calling warmup again", async () => {
    sessionStorage.setItem("bb_fcm_device_id", "session-token");
    mockAuthState.pendingLogin = {
      email: "user@example.com",
    };

    render(<FcmAuthWarmup />);

    await waitFor(() => {
      expect(mockAuthState.setPendingLogin).toHaveBeenCalledWith({
        email: "user@example.com",
        device_id: "session-token",
      });
    });
    expect(warmupFcmForAuth).not.toHaveBeenCalled();
  });
});
