import { describe, it, expect, vi, beforeEach, type Mock } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import LoginPage from "./page";

const { mockPush, mockReplace, mockSearchParams, authState } = vi.hoisted(() => ({
  mockPush: vi.fn(),
  mockReplace: vi.fn(),
  mockSearchParams: new URLSearchParams(),
  authState: {
    isAuthenticated: false,
    refreshSession: vi.fn(),
  },
}));

const { mockFetchWithRetry } = vi.hoisted(() => ({
  mockFetchWithRetry: vi.fn(),
}));

vi.mock("next/navigation", () => ({
  useRouter: (): { push: Mock; replace: Mock } => ({
    push: mockPush,
    replace: mockReplace,
  }),
  useSearchParams: (): URLSearchParams => mockSearchParams,
}));

vi.mock("@/lib/config", () => ({
  API_BASE_URL: "http://localhost:3001",
  IS_MOCK_AUTH_MODE: true,
}));

vi.mock("@/lib/auth-client", () => ({
  signIn: {
    oauth2: vi.fn(),
    email: vi.fn(),
  },
}));

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

vi.mock("@/lib/auth/fetch-with-retry", () => ({
  fetchWithRetry: mockFetchWithRetry,
}));

describe("LoginPage (mock auth mode)", (): void => {
  beforeEach((): void => {
    vi.clearAllMocks();
    mockSearchParams.delete("error");
    authState.isAuthenticated = false;
    authState.refreshSession.mockResolvedValue(undefined);
  });

  it("should render mock auth controls", (): void => {
    render(<LoginPage />);

    expect(screen.getByText(/local mock auth mode is active/i)).toBeInTheDocument();
    expect(screen.getByTestId("mock-auth-login")).toBeInTheDocument();
    expect(mockFetchWithRetry).not.toHaveBeenCalled();
  });

  it("should continue with mock session and navigate to tasks", async (): Promise<void> => {
    const user = userEvent.setup();
    render(<LoginPage />);

    await user.click(screen.getByTestId("mock-auth-login"));

    await waitFor(() => {
      expect(authState.refreshSession).toHaveBeenCalledTimes(1);
      expect(mockPush).toHaveBeenCalledWith("/tasks");
    });
  });

  it("should auto-redirect authenticated mock users to tasks", async (): Promise<void> => {
    authState.isAuthenticated = true;
    render(<LoginPage />);

    await waitFor(() => {
      expect(mockReplace).toHaveBeenCalledWith("/tasks");
    });
  });
});
