import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { vi, describe, it, expect, beforeEach } from "vitest";
import RegisterForm from "./RegisterForm";
import { register } from "@/actions/register";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import React from "react";

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

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

// Mock sonner
vi.mock("sonner", () => ({
  toast: {
    success: vi.fn(),
    error: vi.fn(),
  },
}));

describe("RegisterForm", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

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

    expect(screen.getByLabelText("Vorname")).toBeInTheDocument();
    expect(screen.getByLabelText("Nachname")).toBeInTheDocument();
    expect(screen.getByLabelText("E-Mail")).toBeInTheDocument();
    expect(screen.getByLabelText("Passwort")).toBeInTheDocument();
    expect(
      screen.getByRole("button", { name: /jetzt registrieren/i })
    ).toBeInTheDocument();
  });

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

    fireEvent.click(screen.getByRole("button", { name: /jetzt registrieren/i }));

    await waitFor(() => {
      expect(screen.getAllByText("Mindestens 2 Zeichen erforderlich")).toHaveLength(2);
      expect(screen.getByText("E-Mail ist erforderlich")).toBeInTheDocument();
      expect(screen.getByText("Mindestens 6 Zeichen erforderlich")).toBeInTheDocument();
    });
  });

  it("shows error message from server via toast", async () => {
    vi.mocked(register).mockResolvedValue({ success: false, error: "Email already exists", code: 409 });

    render(<RegisterForm />);

    fireEvent.change(screen.getByLabelText("Vorname"), { target: { value: "John" } });
    fireEvent.change(screen.getByLabelText("Nachname"), { target: { value: "Doe" } });
    fireEvent.change(screen.getByLabelText("E-Mail"), { target: { value: "test@example.com" } });
    fireEvent.change(screen.getByLabelText("Passwort"), { target: { value: "password123" } });

    fireEvent.submit(screen.getByRole("button", { name: /jetzt registrieren/i }).closest("form")!);

    await waitFor(() => {
      expect(toast.error).toHaveBeenCalledWith("Email already exists");
    });
  });

  it("shows success message and redirects on successful registration", async () => {
    vi.mocked(register).mockResolvedValue({ success: true, data: { userId: "1" }, code: 201 });

    render(<RegisterForm />);

    fireEvent.change(screen.getByLabelText("Vorname"), { target: { value: "John" } });
    fireEvent.change(screen.getByLabelText("Nachname"), { target: { value: "Doe" } });
    fireEvent.change(screen.getByLabelText("E-Mail"), { target: { value: "test@example.com" } });
    fireEvent.change(screen.getByLabelText("Passwort"), { target: { value: "password123" } });

    fireEvent.submit(screen.getByRole("button", { name: /jetzt registrieren/i }).closest("form")!);

    await waitFor(() => {
      // In useAction, success message is optional, but if result.success is true, it redirects
      expect(mockPush).toHaveBeenCalledWith("/auth/login");
    });
  });
});
