import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
import { vi, describe, it, expect, beforeEach } from "vitest";
import LoginForm from "./LoginForm";
import { login } from "@/actions/login";
import { useSearchParams } from "next/navigation";
import React from "react";

// Mock next/navigation
vi.mock("next/navigation", () => ({
  useSearchParams: vi.fn(),
}));

// Mock login action
vi.mock("@/actions/login", () => ({
  login: vi.fn(),
}));

describe("LoginForm", () => {
  const mockGet = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(useSearchParams).mockReturnValue({
      get: mockGet,
    } as any);
  });

  it("renders the login form correctly", () => {
    render(<LoginForm />);

    expect(screen.getByLabelText("E-Mail")).toBeInTheDocument();
    expect(screen.getByLabelText("Passwort")).toBeInTheDocument();
    expect(screen.getByRole("button", { name: /^login$/i })).toBeInTheDocument();
  });

  it("shows validation errors for empty fields", async () => {
    render(<LoginForm />);

    fireEvent.click(screen.getByRole("button", { name: /^login$/i }));

    await waitFor(() => {
      expect(screen.getByText("E-Mail ist erforderlich")).toBeInTheDocument();
      expect(screen.getByText("Passwort ist erforderlich")).toBeInTheDocument();
    });
  });

  it("shows error message from server", async () => {
    vi.mocked(login).mockResolvedValue({ success: false, error: "E-Mail oder Passwort falsch!", code: 401 });

    render(<LoginForm />);

    fireEvent.change(screen.getByLabelText("E-Mail"), {
      target: { value: "test@example.com" },
    });
    fireEvent.change(screen.getByLabelText("Passwort"), {
      target: { value: "password123" },
    });
    fireEvent.click(screen.getByRole("button", { name: /^login$/i }));

    await waitFor(() => {
      expect(screen.getByText("E-Mail oder Passwort falsch!")).toBeInTheDocument();
    });
  });

  it("calls login action on submission", async () => {
    vi.mocked(login).mockResolvedValue({ success: true, data: { email: "test@example.com" }, code: 200 });

    render(<LoginForm />);

    fireEvent.change(screen.getByLabelText("E-Mail"), {
      target: { value: "test@example.com" },
    });
    fireEvent.change(screen.getByLabelText("Passwort"), {
      target: { value: "password123" },
    });
    fireEvent.click(screen.getByRole("button", { name: /^login$/i }));

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

  it("displays URL error when OAuthAccountNotLinked is present", () => {
    mockGet.mockImplementation((key) => {
      if (key === "error") return "OAuthAccountNotLinked";
      return null;
    });

    render(<LoginForm />);

    expect(
      screen.getByText("Bitte verknüpfen Sie Ihr Konto mit Google.")
    ).toBeInTheDocument();
  });
});
