// TopWrongQuestionList 组件单测
// 依据：02-architecture-design.md §15 组件设计
// 覆盖：空态 / 列表渲染 / 题干截断 / 学科标签 / 错误次数 / 掌握率 / 进度条 / 最后错误时间

import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { TopWrongQuestionList } from "./TopWrongQuestionList";
import type { TopWrongQuestion } from "@/types";

function makeQuestions(overrides: Partial<TopWrongQuestion>[] = []): TopWrongQuestion[] {
  const base: TopWrongQuestion[] = [
    {
      id: "wq-001",
      questionContent: "已知一元二次方程 x² - 5x + 6 = 0，求方程的解。",
      subject: "数学",
      knowledgePoint: "一元二次方程",
      errorCount: 5,
      lastErrorAt: "2026-07-08T15:20:00Z",
      masteryRate: 0.4,
    },
    {
      id: "wq-002",
      questionContent: "下列句子中，加点词语使用正确的一项是（ ）",
      subject: "语文",
      knowledgePoint: "词语辨析",
      errorCount: 4,
      lastErrorAt: "2026-07-06T16:10:00Z",
      masteryRate: 0.85,
    },
  ];
  if (overrides.length === 0) return base;
  return base.map((q, i) => ({ ...q, ...overrides[i] }));
}

describe("TopWrongQuestionList 空态", () => {
  it("空数组渲染暂无错题数据", () => {
    render(<TopWrongQuestionList questions={[]} />);
    expect(screen.getByText("暂无错题数据")).toBeInTheDocument();
  });
});

describe("TopWrongQuestionList 列表渲染", () => {
  it("渲染列表 region（aria-label）", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    expect(screen.getByLabelText("高频错题列表")).toBeInTheDocument();
  });

  it("渲染每条题干", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    expect(
      screen.getByText("已知一元二次方程 x² - 5x + 6 = 0，求方程的解。"),
    ).toBeInTheDocument();
    expect(
      screen.getByText("下列句子中，加点词语使用正确的一项是（ ）"),
    ).toBeInTheDocument();
  });

  it("渲染每条学科标签", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    expect(screen.getByText("数学")).toBeInTheDocument();
    expect(screen.getByText("语文")).toBeInTheDocument();
  });

  it("渲染每条知识点", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    expect(screen.getByText("一元二次方程")).toBeInTheDocument();
    expect(screen.getByText("词语辨析")).toBeInTheDocument();
  });

  it("渲染每条错误次数", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    expect(screen.getByText("错 5 次")).toBeInTheDocument();
    expect(screen.getByText("错 4 次")).toBeInTheDocument();
  });

  it("渲染每条掌握率（百分比）", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    // 0.4 → 40.0%，0.85 → 85.0%
    expect(screen.getByText(/40\.0%/)).toBeInTheDocument();
    expect(screen.getByText(/85\.0%/)).toBeInTheDocument();
  });

  it("渲染每条最后错误时间", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    expect(screen.getAllByText(/最后错误：/)).toHaveLength(2);
  });
});

describe("TopWrongQuestionList 题干截断", () => {
  it("题干超过 80 字符时截断并加省略号", () => {
    const longContent = "a".repeat(100);
    const questions: TopWrongQuestion[] = [
      {
        id: "wq-long",
        questionContent: longContent,
        subject: "数学",
        knowledgePoint: "测试",
        errorCount: 1,
        lastErrorAt: "2026-07-08T15:20:00Z",
        masteryRate: 0.5,
      },
    ];
    render(<TopWrongQuestionList questions={questions} />);
    const expected = `${"a".repeat(80)}…`;
    expect(screen.getByText(expected)).toBeInTheDocument();
  });

  it("题干等于 80 字符时不截断", () => {
    const exactContent = "a".repeat(80);
    const questions: TopWrongQuestion[] = [
      {
        id: "wq-exact",
        questionContent: exactContent,
        subject: "数学",
        knowledgePoint: "测试",
        errorCount: 1,
        lastErrorAt: "2026-07-08T15:20:00Z",
        masteryRate: 0.5,
      },
    ];
    render(<TopWrongQuestionList questions={questions} />);
    expect(screen.getByText(exactContent)).toBeInTheDocument();
  });
});

describe("TopWrongQuestionList 掌握率进度条", () => {
  it("每条记录渲染 progressbar 角色", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    const bars = screen.getAllByRole("progressbar");
    expect(bars).toHaveLength(2);
  });

  it("掌握率 < 0.6 时进度条用 danger 色（isWeak）", () => {
    const { container } = render(
      <TopWrongQuestionList questions={makeQuestions()} />,
    );
    const dangerBars = container.querySelectorAll(".bg-danger");
    // masteryRate=0.4 < 0.6，有 1 个 danger 进度条
    expect(dangerBars.length).toBeGreaterThanOrEqual(1);
  });

  it("掌握率 >= 0.6 时进度条用 success 色", () => {
    const { container } = render(
      <TopWrongQuestionList questions={makeQuestions()} />,
    );
    const successBars = container.querySelectorAll(".bg-success");
    // masteryRate=0.85 >= 0.6，有 1 个 success 进度条
    expect(successBars.length).toBeGreaterThanOrEqual(1);
  });

  it("progressbar aria-valuenow 反映掌握率百分比", () => {
    render(<TopWrongQuestionList questions={makeQuestions()} />);
    const bars = screen.getAllByRole("progressbar");
    // 0.4 → 40，0.85 → 85
    expect(bars[0]).toHaveAttribute("aria-valuenow", "40");
    expect(bars[1]).toHaveAttribute("aria-valuenow", "85");
  });
});
