import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import CallbackPage from "./page";

// Mock next/navigation
const mockPush = vi.fn();
const mockSearchParams = new Map<string, string>();

vi.mock("next/navigation", () => ({
  useRouter: () => ({
    push: mockPush,
  }),
  useSearchParams: () => ({
    get: (key: string) => mockSearchParams.get(key),
  }),
}));

// Mock auth context
vi.mock("@/lib/auth/auth-context", () => ({
  useAuth: vi.fn(() => ({
    refreshSession: vi.fn(),
  })),
}));

const { useAuth } = await import("@/lib/auth/auth-context");

describe("CallbackPage", (): void => {
  beforeEach((): void => {
    mockPush.mockClear();
    mockSearchParams.clear();
    vi.mocked(useAuth).mockReturnValue({
      refreshSession: vi.fn(),
      user: null,
      isLoading: false,
      isAuthenticated: false,
      signOut: vi.fn(),
    });
  });

  it("should render processing message", (): void => {
    render(<CallbackPage />);
    expect(screen.getByText(/completing authentication/i)).toBeInTheDocument();
  });

  it("should redirect to tasks page on success", async (): Promise<void> => {
    const mockRefreshSession = vi.fn().mockResolvedValue(undefined);
    vi.mocked(useAuth).mockReturnValue({
      refreshSession: mockRefreshSession,
      user: null,
      isLoading: false,
      isAuthenticated: false,
      signOut: vi.fn(),
    });

    render(<CallbackPage />);

    await waitFor(() => {
      expect(mockRefreshSession).toHaveBeenCalled();
      expect(mockPush).toHaveBeenCalledWith("/tasks");
    });
  });

  it("should redirect to login on error parameter", async (): Promise<void> => {
    mockSearchParams.set("error", "access_denied");
    mockSearchParams.set("error_description", "User cancelled");

    render(<CallbackPage />);

    await waitFor(() => {
      expect(mockPush).toHaveBeenCalledWith("/login?error=access_denied");
    });
  });

  it("should handle refresh session errors gracefully", async (): Promise<void> => {
    const mockRefreshSession = vi.fn().mockRejectedValue(new Error("Session error"));
    vi.mocked(useAuth).mockReturnValue({
      refreshSession: mockRefreshSession,
      user: null,
      isLoading: false,
      isAuthenticated: false,
      signOut: vi.fn(),
    });

    render(<CallbackPage />);

    await waitFor(() => {
      expect(mockRefreshSession).toHaveBeenCalled();
      expect(mockPush).toHaveBeenCalledWith("/login?error=session_failed");
    });
  });
});
