import { fireEvent, screen, waitFor } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "../utils/testHelpers";
import { LoginPage } from "./login";

const mockLogin = vi.fn();

vi.mock("../hooks/auth", () => ({
  useLoginEmail: () => ({
    mutate: mockLogin,
    isPending: false,
    errors: null,
  }),
  useLoginGoogle: () => ({
    mutate: vi.fn(),
  }),
  useSignUp: () => ({
    mutate: vi.fn(),
    isPending: false,
  }),
}));

describe("LoginPage", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    localStorage.clear();
  });

  it("renders without crashing", () => {
    const { container } = renderWithProviders(<LoginPage />);
    expect(container).toBeInTheDocument();
  });

  it("renders all form elements", () => {
    renderWithProviders(<LoginPage />);

    expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
    expect(screen.getByRole("button", { name: /log in/i })).toBeInTheDocument();
  });

  it("displays theme toggle button", () => {
    renderWithProviders(<LoginPage />);

    const themeButton = screen.getByRole("button", { name: /change theme/i });
    expect(themeButton).toBeInTheDocument();
  });

  it("shows link to signup page", () => {
    renderWithProviders(<LoginPage />);

    const signupLink = screen.getByText(/sign up/i);
    expect(signupLink).toBeInTheDocument();
  });

  it("updates email input on change", () => {
    renderWithProviders(<LoginPage />);

    const emailInput = screen.getByPlaceholderText(/your email/i) as HTMLInputElement;
    fireEvent.change(emailInput, { target: { value: "test@example.com" } });

    expect(emailInput.value).toBe("test@example.com");
  });

  it("updates password input on change", () => {
    renderWithProviders(<LoginPage />);

    const passwordInput = screen.getByPlaceholderText(/your password/i) as HTMLInputElement;
    fireEvent.change(passwordInput, { target: { value: "password123" } });

    expect(passwordInput.value).toBe("password123");
  });

  it("submits form with email and password", async () => {
    renderWithProviders(<LoginPage />);

    const emailInput = screen.getByPlaceholderText(/your email/i);
    const passwordInput = screen.getByPlaceholderText(/your password/i);
    const submitButton = screen.getByRole("button", { name: /log in/i });

    fireEvent.change(emailInput, { target: { value: "test@example.com" } });
    fireEvent.change(passwordInput, { target: { value: "password123" } });
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(mockLogin).toHaveBeenCalledWith({
        email: "test@example.com",
        password: "password123",
      });
    });
  });

  it("uses redirectUrl from localStorage when available", () => {
    localStorage.setItem("redirectUrl", "/dashboard");
    renderWithProviders(<LoginPage />);

    // Component should read from localStorage
    expect(localStorage.getItem("redirectUrl")).toBe("/dashboard");
  });

  it("prevents form submission when fields are empty", () => {
    renderWithProviders(<LoginPage />);

    const submitButton = screen.getByRole("button", { name: /log in/i });
    fireEvent.click(submitButton);

    // Form should not submit due to HTML5 validation (required fields)
    expect(mockLogin).not.toHaveBeenCalled();
  });
});
