import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";

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

// Mock Supabase
const mockSignInWithPassword = vi.fn();
const mockSignInWithOtp = vi.fn();
vi.mock("@/lib/supabase/client", () => ({
  createClient: () => ({
    auth: {
      signInWithPassword: mockSignInWithPassword,
      signInWithOtp: mockSignInWithOtp,
    },
  }),
}));

// Import after mocks
const { default: LoginPage } = await import(
  "@/app/(auth)/login/page"
);

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

  it("renders login form with email and password fields", () => {
    render(<LoginPage />);

    expect(screen.getByText("KanzlAI")).toBeInTheDocument();
    expect(screen.getByText("Melden Sie sich an")).toBeInTheDocument();
    expect(screen.getByLabelText("E-Mail")).toBeInTheDocument();
    expect(screen.getByLabelText("Passwort")).toBeInTheDocument();
    expect(screen.getByText("Anmelden")).toBeInTheDocument();
  });

  it("renders mode toggle between Passwort and Magic Link", () => {
    render(<LoginPage />);

    // "Passwort" appears twice (toggle button + label), so use getAllByText
    const passwortElements = screen.getAllByText("Passwort");
    expect(passwortElements.length).toBeGreaterThanOrEqual(1);
    expect(screen.getByText("Magic Link")).toBeInTheDocument();
  });

  it("switches to magic link mode and hides password field", () => {
    render(<LoginPage />);

    fireEvent.click(screen.getByText("Magic Link"));

    expect(screen.queryByLabelText("Passwort")).not.toBeInTheDocument();
    expect(screen.getByText("Link senden")).toBeInTheDocument();
  });

  it("submits password login to Supabase", async () => {
    mockSignInWithPassword.mockResolvedValue({ error: null });
    render(<LoginPage />);

    fireEvent.change(screen.getByLabelText("E-Mail"), {
      target: { value: "test@kanzlei.de" },
    });
    fireEvent.change(screen.getByLabelText("Passwort"), {
      target: { value: "geheim123" },
    });
    fireEvent.click(screen.getByText("Anmelden"));

    await waitFor(() => {
      expect(mockSignInWithPassword).toHaveBeenCalledWith({
        email: "test@kanzlei.de",
        password: "geheim123",
      });
    });
  });

  it("redirects to / on successful login", async () => {
    mockSignInWithPassword.mockResolvedValue({ error: null });
    render(<LoginPage />);

    fireEvent.change(screen.getByLabelText("E-Mail"), {
      target: { value: "test@kanzlei.de" },
    });
    fireEvent.change(screen.getByLabelText("Passwort"), {
      target: { value: "geheim123" },
    });
    fireEvent.click(screen.getByText("Anmelden"));

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

  it("displays error on failed login", async () => {
    mockSignInWithPassword.mockResolvedValue({
      error: { message: "Ungültige Anmeldedaten" },
    });
    render(<LoginPage />);

    fireEvent.change(screen.getByLabelText("E-Mail"), {
      target: { value: "bad@email.de" },
    });
    fireEvent.change(screen.getByLabelText("Passwort"), {
      target: { value: "wrong" },
    });
    fireEvent.click(screen.getByText("Anmelden"));

    await waitFor(() => {
      expect(screen.getByText("Ungültige Anmeldedaten")).toBeInTheDocument();
    });
  });

  it("shows magic link sent confirmation", async () => {
    mockSignInWithOtp.mockResolvedValue({ error: null });
    render(<LoginPage />);

    // Switch to magic link mode
    fireEvent.click(screen.getByText("Magic Link"));

    fireEvent.change(screen.getByLabelText("E-Mail"), {
      target: { value: "test@kanzlei.de" },
    });
    fireEvent.click(screen.getByText("Link senden"));

    await waitFor(() => {
      expect(screen.getByText("Link gesendet")).toBeInTheDocument();
      expect(screen.getByText("Zurueck zum Login")).toBeInTheDocument();
    });
  });

  it("has link to registration page", () => {
    render(<LoginPage />);

    const registerLink = screen.getByText("Registrieren");
    expect(registerLink).toBeInTheDocument();
    expect(registerLink.closest("a")).toHaveAttribute("href", "/register");
  });
});
