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

const mockSignUp = vi.fn();

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

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

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

  it("renders all form fields", () => {
    renderWithProviders(<SignUpPage />);

    expect(screen.getByLabelText(/first name/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/last name/i)).toBeInTheDocument();
    expect(screen.getByLabelText(/professional email/i)).toBeInTheDocument();
    expect(screen.getAllByLabelText(/password/i)[0]).toBeInTheDocument();
    expect(screen.getByLabelText(/confirm password/i)).toBeInTheDocument();
    expect(screen.getByRole("button", { name: /create my account/i })).toBeInTheDocument();
  });

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

    const loginLink = screen.getByText(/log in/i);
    expect(loginLink).toBeInTheDocument();
  });

  it("updates form fields on change", () => {
    renderWithProviders(<SignUpPage />);

    const firstNameInput = screen.getByPlaceholderText(/your first name/i) as HTMLInputElement;
    const lastNameInput = screen.getByPlaceholderText(/your last name/i) as HTMLInputElement;
    const emailInput = screen.getByPlaceholderText(/your email/i) as HTMLInputElement;
    const passwordInput = screen.getAllByPlaceholderText(/your password/i)[0] as HTMLInputElement;
    const confirmPasswordInput = screen.getByPlaceholderText(
      /confirm your password/i
    ) as HTMLInputElement;

    fireEvent.change(firstNameInput, { target: { value: "John" } });
    fireEvent.change(lastNameInput, { target: { value: "Doe" } });
    fireEvent.change(emailInput, { target: { value: "john@example.com" } });
    fireEvent.change(passwordInput, { target: { value: "password123" } });
    fireEvent.change(confirmPasswordInput, { target: { value: "password123" } });

    expect(firstNameInput.value).toBe("John");
    expect(lastNameInput.value).toBe("Doe");
    expect(emailInput.value).toBe("john@example.com");
    expect(passwordInput.value).toBe("password123");
    expect(confirmPasswordInput.value).toBe("password123");
  });

  it("shows error when password is too short", async () => {
    renderWithProviders(<SignUpPage />);

    const passwordInput = screen.getAllByPlaceholderText(/your password/i)[0];
    const confirmPasswordInput = screen.getByPlaceholderText(/confirm your password/i);
    const submitButton = screen.getByRole("button", { name: /create my account/i });
    const termsCheckbox = screen.getByRole("checkbox", { name: /i accept/i });

    fireEvent.change(screen.getByPlaceholderText(/your first name/i), {
      target: { value: "John" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your last name/i), {
      target: { value: "Doe" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your email/i), {
      target: { value: "john@example.com" },
    });
    fireEvent.change(passwordInput, { target: { value: "short" } });
    fireEvent.change(confirmPasswordInput, { target: { value: "short" } });
    fireEvent.click(termsCheckbox);
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(screen.getByText(/password must be at least 8 characters/i)).toBeInTheDocument();
    });

    expect(mockSignUp).not.toHaveBeenCalled();
  });

  it("shows error when passwords don't match", async () => {
    renderWithProviders(<SignUpPage />);

    const passwordInput = screen.getAllByPlaceholderText(/your password/i)[0];
    const confirmPasswordInput = screen.getByPlaceholderText(/confirm your password/i);
    const submitButton = screen.getByRole("button", { name: /create my account/i });
    const termsCheckbox = screen.getByRole("checkbox", { name: /i accept/i });

    fireEvent.change(screen.getByPlaceholderText(/your first name/i), {
      target: { value: "John" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your last name/i), {
      target: { value: "Doe" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your email/i), {
      target: { value: "john@example.com" },
    });
    fireEvent.change(passwordInput, { target: { value: "password123" } });
    fireEvent.change(confirmPasswordInput, { target: { value: "different123" } });
    fireEvent.click(termsCheckbox);
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(screen.getByText(/passwords do not match/i)).toBeInTheDocument();
    });

    expect(mockSignUp).not.toHaveBeenCalled();
  });

  it.skip("shows error for invalid email", async () => {
    renderWithProviders(<SignUpPage />);

    const submitButton = screen.getByRole("button", { name: /auth:signup.signupButton/i });
    const termsCheckbox = screen.getByRole("checkbox", { name: /auth:signup.termsAccept/i });

    fireEvent.change(screen.getByPlaceholderText(/auth:signup.firstNamePlaceholder/i), {
      target: { value: "John" },
    });
    fireEvent.change(screen.getByPlaceholderText(/auth:signup.lastNamePlaceholder/i), {
      target: { value: "Doe" },
    });
    fireEvent.change(screen.getByPlaceholderText(/auth:signup.emailPlaceholder/i), {
      target: { value: "invalid-email" },
    });
    fireEvent.change(screen.getByPlaceholderText(/auth:signup.passwordPlaceholder/i), {
      target: { value: "password123" },
    });
    fireEvent.change(screen.getByPlaceholderText(/auth:signup.confirmPasswordPlaceholder/i), {
      target: { value: "password123" },
    });
    fireEvent.click(termsCheckbox);
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(screen.getByText(/auth:signup.errors.invalidEmail/i)).toBeInTheDocument();
    });

    expect(mockSignUp).not.toHaveBeenCalled();
  });

  it("submits form with valid data", async () => {
    renderWithProviders(<SignUpPage />);

    const submitButton = screen.getByRole("button", { name: /create my account/i });
    const termsCheckbox = screen.getByRole("checkbox", { name: /i accept/i });

    fireEvent.change(screen.getByPlaceholderText(/your first name/i), {
      target: { value: "John" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your last name/i), {
      target: { value: "Doe" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your email/i), {
      target: { value: "john@example.com" },
    });
    fireEvent.change(screen.getAllByPlaceholderText(/your password/i)[0], {
      target: { value: "password123" },
    });
    fireEvent.change(screen.getByPlaceholderText(/confirm your password/i), {
      target: { value: "password123" },
    });
    fireEvent.click(termsCheckbox);
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(mockSignUp).toHaveBeenCalledWith({
        email: "john@example.com",
        password: "password123",
        first_name: "John",
        last_name: "Doe",
        confirm_password: "password123",
        business_name: "",
        billing_intent: "solo",
      });
    });
  });

  it("submits team billing intent when selected", async () => {
    renderWithProviders(<SignUpPage />);

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

    const submitButton = screen.getByRole("button", { name: /create my account/i });
    const termsCheckbox = screen.getByRole("checkbox", { name: /i accept/i });

    fireEvent.change(screen.getByPlaceholderText(/your first name/i), {
      target: { value: "John" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your last name/i), {
      target: { value: "Doe" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your email/i), {
      target: { value: "john@example.com" },
    });
    fireEvent.change(screen.getAllByPlaceholderText(/your password/i)[0], {
      target: { value: "password123" },
    });
    fireEvent.change(screen.getByPlaceholderText(/confirm your password/i), {
      target: { value: "password123" },
    });
    fireEvent.click(termsCheckbox);
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(mockSignUp).toHaveBeenCalledWith(expect.objectContaining({ billing_intent: "team" }));
    });
  });

  it("submits founder billing intent when selected", async () => {
    renderWithProviders(<SignUpPage />);

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

    const submitButton = screen.getByRole("button", { name: /create my account/i });
    const termsCheckbox = screen.getByRole("checkbox", { name: /i accept/i });

    fireEvent.change(screen.getByPlaceholderText(/your first name/i), {
      target: { value: "John" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your last name/i), {
      target: { value: "Doe" },
    });
    fireEvent.change(screen.getByPlaceholderText(/your email/i), {
      target: { value: "john@example.com" },
    });
    fireEvent.change(screen.getAllByPlaceholderText(/your password/i)[0], {
      target: { value: "password123" },
    });
    fireEvent.change(screen.getByPlaceholderText(/confirm your password/i), {
      target: { value: "password123" },
    });
    fireEvent.click(termsCheckbox);
    fireEvent.click(submitButton);

    await waitFor(() => {
      expect(mockSignUp).toHaveBeenCalledWith(
        expect.objectContaining({ billing_intent: "founder" })
      );
    });
  });

  it("requires terms checkbox to be checked", () => {
    renderWithProviders(<SignUpPage />);

    const termsCheckbox = screen.getByRole("checkbox", { name: /i accept/i });
    expect(termsCheckbox).toHaveAttribute("required");
  });
});
