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

// Mock next/navigation
const mockPush = vi.fn();
vi.mock("next/navigation", () => ({
  useRouter: (): { push: typeof mockPush } => ({
    push: mockPush,
  }),
}));

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

describe("LogoutButton", (): void => {
  beforeEach((): void => {
    mockPush.mockClear();
    mockSignOut.mockClear();
  });

  it("should render sign out button", (): void => {
    render(<LogoutButton />);
    const button = screen.getByRole("button", { name: /sign out/i });
    expect(button).toBeInTheDocument();
  });

  it("should call signOut and redirect on click", async (): Promise<void> => {
    const user = userEvent.setup();
    mockSignOut.mockResolvedValue(undefined);

    render(<LogoutButton />);

    const button = screen.getByRole("button", { name: /sign out/i });
    await user.click(button);

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

  it("should redirect to login even if signOut fails", async (): Promise<void> => {
    const user = userEvent.setup();
    mockSignOut.mockRejectedValue(new Error("Sign out failed"));

    // Suppress console.error for this test
    const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {
      // Intentionally empty - suppressing error output
    });

    render(<LogoutButton />);

    const button = screen.getByRole("button", { name: /sign out/i });
    await user.click(button);

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

    consoleErrorSpy.mockRestore();
  });

  it("should have secondary variant by default", (): void => {
    render(<LogoutButton />);
    const button = screen.getByRole("button", { name: /sign out/i });
    // The Button component from @mosaic/ui should apply the variant
    expect(button).toBeInTheDocument();
  });

  it("should accept custom variant prop", (): void => {
    render(<LogoutButton variant="primary" />);
    const button = screen.getByRole("button", { name: /sign out/i });
    expect(button).toBeInTheDocument();
  });
});
