// ChildSwitcher 组件单测
// 依据：02-architecture-design.md §15.1 ChildSwitcher 设计、§13 测试策略
// 覆盖：加载态 / 无子女空态 / 单子女显示 / 多子女下拉切换 / 键盘可访问性

import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ChildSwitcher } from "./ChildSwitcher";
import type { ChildInfo } from "@/types";

// mock useChildSwitcher hook
vi.mock("@/hooks/useChildSwitcher", () => ({
  useChildSwitcher: vi.fn(),
}));

import { useChildSwitcher } from "@/hooks/useChildSwitcher";

const mockChildren: ChildInfo[] = [
  {
    id: "student-001",
    name: "张小明",
    grade: "grade.7",
    schoolName: "实验中学",
    classId: "class-7-1",
    className: "初一(1)班",
  },
  {
    id: "student-002",
    name: "张小红",
    grade: "grade.5",
    schoolName: "实验小学",
    classId: "class-5-2",
    className: "五年级(2)班",
  },
];

const mockUseChildSwitcher = vi.mocked(useChildSwitcher);

beforeEach(() => {
  mockUseChildSwitcher.mockReset();
});

describe("ChildSwitcher 加载态", () => {
  it("loading 时显示骨架屏", () => {
    mockUseChildSwitcher.mockReturnValue({
      children: [],
      currentChild: null,
      currentChildId: null,
      switchChild: vi.fn(),
      loading: true,
      error: undefined,
      hasMultipleChildren: false,
    });
    render(<ChildSwitcher />);
    expect(screen.getByLabelText("加载子女列表")).toBeInTheDocument();
  });
});

describe("ChildSwitcher 无子女", () => {
  it("空列表时显示未绑定提示", () => {
    mockUseChildSwitcher.mockReturnValue({
      children: [],
      currentChild: null,
      currentChildId: null,
      switchChild: vi.fn(),
      loading: false,
      error: undefined,
      hasMultipleChildren: false,
    });
    render(<ChildSwitcher />);
    expect(screen.getByLabelText("未绑定子女")).toBeInTheDocument();
  });
});

describe("ChildSwitcher 单子女", () => {
  it("仅显示子女名称（无下拉）", () => {
    mockUseChildSwitcher.mockReturnValue({
      children: [mockChildren[0]!],
      currentChild: mockChildren[0]!,
      currentChildId: "student-001",
      switchChild: vi.fn(),
      loading: false,
      error: undefined,
      hasMultipleChildren: false,
    });
    render(<ChildSwitcher />);
    expect(screen.getByLabelText("当前子女")).toHaveTextContent("张小明");
    // 不应有下拉按钮
    expect(screen.queryByRole("button")).not.toBeInTheDocument();
  });
});

describe("ChildSwitcher 多子女", () => {
  beforeEach(() => {
    mockUseChildSwitcher.mockReturnValue({
      children: mockChildren,
      currentChild: mockChildren[0]!,
      currentChildId: "student-001",
      switchChild: vi.fn(),
      loading: false,
      error: undefined,
      hasMultipleChildren: true,
    });
  });

  it("显示当前子女名称和切换按钮", () => {
    render(<ChildSwitcher />);
    const button = screen.getByRole("button", { name: "选择子女" });
    expect(button).toBeInTheDocument();
    expect(screen.getByText("张小明")).toBeInTheDocument();
  });

  it("点击按钮展开子女列表", async () => {
    const user = userEvent.setup();
    render(<ChildSwitcher />);
    const button = screen.getByRole("button", { name: "选择子女" });
    await user.click(button);
    expect(
      screen.getByRole("listbox", { name: "子女列表" }),
    ).toBeInTheDocument();
    expect(screen.getByText("张小红")).toBeInTheDocument();
  });

  it("点击子女项触发 switchChild 并关闭列表", async () => {
    const user = userEvent.setup();
    const switchChild = vi.fn();
    mockUseChildSwitcher.mockReturnValue({
      children: mockChildren,
      currentChild: mockChildren[0]!,
      currentChildId: "student-001",
      switchChild,
      loading: false,
      error: undefined,
      hasMultipleChildren: true,
    });
    render(<ChildSwitcher />);
    await user.click(screen.getByRole("button", { name: "选择子女" }));
    await user.click(screen.getByText("张小红"));
    expect(switchChild).toHaveBeenCalledWith("student-002");
    expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
  });

  it("Escape 键关闭列表", async () => {
    const user = userEvent.setup();
    render(<ChildSwitcher />);
    const button = screen.getByRole("button", { name: "选择子女" });
    await user.click(button);
    expect(screen.getByRole("listbox")).toBeInTheDocument();
    fireEvent.keyDown(button, { key: "Escape" });
    expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
  });

  it("aria-expanded 反映展开状态", async () => {
    const user = userEvent.setup();
    render(<ChildSwitcher />);
    const button = screen.getByRole("button", { name: "选择子女" });
    expect(button).toHaveAttribute("aria-expanded", "false");
    await user.click(button);
    expect(button).toHaveAttribute("aria-expanded", "true");
  });

  it("当前选中项有 aria-selected=true", async () => {
    const user = userEvent.setup();
    render(<ChildSwitcher />);
    await user.click(screen.getByRole("button", { name: "选择子女" }));
    const options = screen.getAllByRole("option");
    expect(options[0]).toHaveAttribute("aria-selected", "true");
    expect(options[1]).toHaveAttribute("aria-selected", "false");
  });
});
