import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { AuthPage } from "./AuthPage";

// 隔离 api 层：只测组件行为（态切换/校验/提交/报错），不打真网络。
vi.mock("../api", () => ({
  authLogin: vi.fn(),
  authRegister: vi.fn(),
}));
import { authLogin, authRegister } from "../api";

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

  it("默认登录态：无名字字段，切到注册后出现", async () => {
    render(<AuthPage onAuthed={vi.fn()} />);
    // 登录态无「名字」标签
    expect(screen.queryByText(/名字/)).toBeNull();
    await userEvent.click(screen.getByText(/还没有账户/));
    expect(screen.getByText(/名字/)).toBeInTheDocument();
    // 切回登录，名字字段消失
    await userEvent.click(screen.getByText(/已有账户/));
    expect(screen.queryByText(/名字/)).toBeNull();
  });

  it("邮箱或密码为空时提交按钮禁用", async () => {
    render(<AuthPage onAuthed={vi.fn()} />);
    const btn = screen.getByRole("button", { name: "登录" });
    expect(btn).toBeDisabled();
    await userEvent.type(screen.getByPlaceholderText(/you@example/), "a@b.com");
    expect(btn).toBeDisabled(); // 还差密码
    await userEvent.type(screen.getByPlaceholderText("••••••"), "pass123");
    expect(btn).toBeEnabled();
  });

  it("登录成功回调 onAuthed", async () => {
    const user = { id: "u1", email: "a@b.com" };
    (authLogin as ReturnType<typeof vi.fn>).mockResolvedValue(user);
    const onAuthed = vi.fn();
    render(<AuthPage onAuthed={onAuthed} />);
    await userEvent.type(screen.getByPlaceholderText(/you@example/), "a@b.com");
    await userEvent.type(screen.getByPlaceholderText("••••••"), "pass123");
    await userEvent.click(screen.getByRole("button", { name: "登录" }));
    await waitFor(() => expect(onAuthed).toHaveBeenCalledWith(user));
    expect(authLogin).toHaveBeenCalledWith("a@b.com", "pass123");
    expect(authRegister).not.toHaveBeenCalled();
  });

  it("登录失败显示后端错误文案，不回调", async () => {
    (authLogin as ReturnType<typeof vi.fn>).mockRejectedValue(new Error("邮箱或密码不正确"));
    const onAuthed = vi.fn();
    render(<AuthPage onAuthed={onAuthed} />);
    await userEvent.type(screen.getByPlaceholderText(/you@example/), "a@b.com");
    await userEvent.type(screen.getByPlaceholderText("••••••"), "wrong");
    await userEvent.click(screen.getByRole("button", { name: "登录" }));
    await waitFor(() => expect(screen.getByText("邮箱或密码不正确")).toBeInTheDocument());
    expect(onAuthed).not.toHaveBeenCalled();
  });

  it("注册态走 authRegister 并带上名字", async () => {
    const user = { id: "u2", email: "c@d.com", name: "小明" };
    (authRegister as ReturnType<typeof vi.fn>).mockResolvedValue(user);
    const onAuthed = vi.fn();
    render(<AuthPage onAuthed={onAuthed} />);
    await userEvent.click(screen.getByText(/还没有账户/));
    await userEvent.type(screen.getByPlaceholderText(/怎么称呼你/), "小明");
    await userEvent.type(screen.getByPlaceholderText(/you@example/), "c@d.com");
    await userEvent.type(screen.getByPlaceholderText("••••••"), "pass123");
    await userEvent.click(screen.getByRole("button", { name: "注册" }));
    await waitFor(() => expect(onAuthed).toHaveBeenCalledWith(user));
    expect(authRegister).toHaveBeenCalledWith("c@d.com", "pass123", "小明");
  });
});
