// DiagnosticReportList 组件单测
// 依据：02-architecture-design.md §15 组件设计
// 覆盖：空态 / 只显示 published / 标题 / 摘要 / 掌握度分数 / 学科分析 / 发布时间

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

function makeReports(): DiagnosticReport[] {
  return [
    {
      id: "diag-001",
      childId: "student-001",
      title: "2026 春季学期学情诊断报告",
      summary:
        "该生本学期整体学习情况良好，数学和物理掌握较好，语文作文和英语口语为薄弱环节，建议针对性强化。",
      status: "published",
      createdAt: "2026-06-20T09:00:00Z",
      publishedAt: "2026-06-25T10:00:00Z",
      masteryScore: 78,
      subjects: [
        {
          subject: "语文",
          masteryLevel: 0.82,
          strengths: ["阅读理解", "古诗文默写"],
          weaknesses: ["作文立意", "现代文词语辨析"],
          recommendation: "每周练习 1 篇议论文，积累优秀范文素材",
        },
        {
          subject: "数学",
          masteryLevel: 0.55,
          strengths: ["几何证明"],
          weaknesses: ["一元二次方程应用题"],
          recommendation: "完成配方法专项练习 20 道",
        },
      ],
    },
    {
      id: "diag-002",
      childId: "student-001",
      title: "2026 暑期学情预诊断报告（草稿）",
      summary: "基于暑期前练习数据生成的预诊断，待教研组审核发布。",
      status: "draft",
      createdAt: "2026-07-10T14:00:00Z",
      masteryScore: 72,
      subjects: [
        {
          subject: "数学",
          masteryLevel: 0.7,
          strengths: ["代数基础"],
          weaknesses: ["不等式组"],
          recommendation: "暑期完成不等式专项练习册",
        },
      ],
    },
  ];
}

describe("DiagnosticReportList 空态", () => {
  it("空数组渲染暂无已发布的诊断报告", () => {
    render(<DiagnosticReportList reports={[]} />);
    expect(screen.getByText("暂无已发布的诊断报告")).toBeInTheDocument();
  });

  it("仅含 draft 报告时也显示暂无已发布的诊断报告", () => {
    const draftOnly = makeReports().filter((r) => r.status === "draft");
    render(<DiagnosticReportList reports={draftOnly} />);
    expect(screen.getByText("暂无已发布的诊断报告")).toBeInTheDocument();
  });
});

describe("DiagnosticReportList 列表渲染", () => {
  it("只渲染 published 报告（draft 不渲染）", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(
      screen.getByText("2026 春季学期学情诊断报告"),
    ).toBeInTheDocument();
    expect(
      screen.queryByText("2026 暑期学情预诊断报告（草稿）"),
    ).not.toBeInTheDocument();
  });

  it("渲染列表 region（aria-label）", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(screen.getByLabelText("诊断报告列表")).toBeInTheDocument();
  });

  it("渲染报告标题", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(
      screen.getByText("2026 春季学期学情诊断报告"),
    ).toBeInTheDocument();
  });

  it("渲染报告摘要", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(
      screen.getByText(
        "该生本学期整体学习情况良好，数学和物理掌握较好，语文作文和英语口语为薄弱环节，建议针对性强化。",
      ),
    ).toBeInTheDocument();
  });

  it("渲染发布时间", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(screen.getByText(/发布于：/)).toBeInTheDocument();
  });

  it("渲染掌握度分数标签", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(screen.getByText("掌握度分数")).toBeInTheDocument();
  });

  it("渲染掌握度分数数值（78）", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(screen.getByText("78")).toBeInTheDocument();
  });
});

describe("DiagnosticReportList 掌握度分数进度条", () => {
  it("渲染报告级 progressbar", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    const bar = screen.getByRole("progressbar", {
      name: "2026 春季学期学情诊断报告掌握度分数",
    });
    expect(bar).toHaveAttribute("aria-valuenow", "78");
  });

  it("掌握度分数 < 60 时使用 danger 色", () => {
    const reports = makeReports();
    reports[0] = { ...reports[0]!, masteryScore: 45 };
    const { container } = render(<DiagnosticReportList reports={reports} />);
    const dangerBars = container.querySelectorAll(".bg-danger");
    expect(dangerBars.length).toBeGreaterThan(0);
  });

  it("掌握度分数 >= 60 时使用 success 色", () => {
    const { container } = render(
      <DiagnosticReportList reports={makeReports()} />,
    );
    const successBars = container.querySelectorAll(".bg-success");
    expect(successBars.length).toBeGreaterThan(0);
  });
});

describe("DiagnosticReportList 学科分析", () => {
  it("渲染学科分析 region", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(screen.getByLabelText("学科分析")).toBeInTheDocument();
  });

  it("渲染每个学科名称", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    // 语文、数学 在 published 报告中
    expect(screen.getAllByText("语文").length).toBeGreaterThan(0);
    expect(screen.getAllByText("数学").length).toBeGreaterThan(0);
  });

  it("渲染每个学科的优势", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    // published 报告含 2 个学科，"优势" 标签出现 2 次
    expect(screen.getAllByText("优势")).toHaveLength(2);
    expect(screen.getByText("阅读理解、古诗文默写")).toBeInTheDocument();
  });

  it("渲染每个学科的不足", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    // published 报告含 2 个学科，"不足" 标签出现 2 次
    expect(screen.getAllByText("不足")).toHaveLength(2);
    expect(screen.getByText("作文立意、现代文词语辨析")).toBeInTheDocument();
  });

  it("渲染每个学科的建议", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    // published 报告含 2 个学科，"建议" 标签出现 2 次
    expect(screen.getAllByText("建议")).toHaveLength(2);
    expect(
      screen.getByText("每周练习 1 篇议论文，积累优秀范文素材"),
    ).toBeInTheDocument();
  });

  it("渲染每个学科的掌握度 progressbar", () => {
    render(<DiagnosticReportList reports={makeReports()} />);
    expect(screen.getByRole("progressbar", { name: "语文掌握度" })).toBeInTheDocument();
    expect(screen.getByRole("progressbar", { name: "数学掌握度" })).toBeInTheDocument();
  });

  it("学科 masteryLevel < 0.6 时使用 danger 色", () => {
    const { container } = render(
      <DiagnosticReportList reports={makeReports()} />,
    );
    // 数学 masteryLevel=0.55 < 0.6，应有 danger 进度条
    const dangerBars = container.querySelectorAll(".bg-danger");
    expect(dangerBars.length).toBeGreaterThan(0);
  });

  it("优势为空数组时显示 —", () => {
    const reports = makeReports();
    reports[0] = {
      ...reports[0]!,
      subjects: [
        {
          subject: "语文",
          masteryLevel: 0.82,
          strengths: [],
          weaknesses: ["作文立意"],
          recommendation: "多练习",
        },
      ],
    };
    render(<DiagnosticReportList reports={reports} />);
    // strengths 渲染 —
    const allEmDashes = screen.getAllByText("—");
    expect(allEmDashes.length).toBeGreaterThan(0);
  });
});
