// faq.jsx — FAQ
const { useState: useStateF } = React;

const FAQ_DATA = {
  "all": "全部",
  "basics": "基础",
  "graph-vs-play": "公共图谱 vs Playground",
  "data": "数据与隐私",
  "models": "模型",
  "billing": "定价",
};

const QUESTIONS = [
  { cat: "basics", q: "Nodeidea 是什么?", a: "Nodeidea(原 Weavr)是一个为学习而生的知识图谱系统。我们把每个概念存为一个节点,自动连接前置与相邻知识,让你不再以文件夹组织笔记,而是以图谱组织。" },
  { cat: "basics", q: "为谁设计?", a: "为需要系统化学习的人——研究生 / 在职学习者 / 自学者 / 高中以上学生。也适合教师维护教研资源。" },
  { cat: "basics", q: "怎么开始?需要登录吗?", a: "首页直接 Enter 即可匿名使用 5 次 / 天。登录后解锁 50 次 / 月并可保存私有节点。完整功能需要 Pro。" },
  { cat: "basics", q: "支持哪些浏览器?有 mobile app 吗?", a: "桌面端 Chrome / Edge / Safari / Firefox(过去 2 个版本)。移动端目前有 Android App(beta),iOS App 排期 Q3。" },
  { cat: "basics", q: "离线能用吗?", a: "暂不支持完整离线。已下载的笔记可在浏览器缓存里只读浏览,但 AI 对话需要联网。" },

  { cat: "graph-vs-play", q: "Public Graph 和 Playground 有什么区别?", a: "Public Graph 是全局的、所有人共享的知识图谱——你看到的节点其他人也能看到。Playground 是你的私有对话空间——节点 / 文件 / 对话都只属于你。Playground 中你可以引用 [[公共节点]] 但不能反过来修改它们。" },
  { cat: "graph-vs-play", q: "公共节点 vs 私有节点的可见性?", a: "公共节点:全部用户可见可引用,只有 verified 贡献者可编辑。私有节点:仅你自己可见,在你的「我的」页面里,可选择性提交为公共。" },
  { cat: "graph-vs-play", q: "怎么把公共节点导入 Playground?", a: "在图谱里点任意节点 → 详情 drawer 顶部「从这里提问」→ 会创建一个引用该节点的新 Playground 会话。" },
  { cat: "graph-vs-play", q: "节点来源是哪些?", a: "目前比例:Wikipedia ~52% / 教科书章节 ~30% / arXiv & 论文 ~18%。所有节点都标注原始来源 URL,可点击溯源。" },
  { cat: "graph-vs-play", q: "找不到要学的概念怎么办?", a: "搜索框右下角会出现「提交新节点」入口(A14 gap detection)。你提交后我们的爬取流水线会优先索引相关来源,通常 24 小时内出现在图谱上。" },
  { cat: "graph-vs-play", q: "学习路径怎么生成的?", a: "用 hypernym + prereq 拓扑排序生成,不是 LLM 编的——这意味着同一个目标节点的路径是确定且可复现的。Pro 用户可自定义起点与已掌握节点。" },
  { cat: "graph-vs-play", q: "[[节点引用]] chip 是什么?", a: "在对话中用 [[uuid]] 标注的内联节点链接。点击会在新 drawer 打开该节点详情,导出 Markdown 时保留为可点击链接。" },
  { cat: "graph-vs-play", q: "embedding 同步:为什么语义搜索偶尔降级?", a: "我们的向量索引分 Stage A(刚抽取)/ B(对齐中)/ C(全部完成)三阶段。Stage A 节点搜索时只用关键词回退,所以新上传的内容前几分钟可能搜不到。" },
  { cat: "graph-vs-play", q: "Socratic 模式是什么?", a: "Playground 里的一个开关。开启后 Nodeidea 不直接给答案,而是反问你引导你自己得出。适合需要深度理解而不是快速 lookup 的场景。" },
  { cat: "graph-vs-play", q: "PDF 上传后会发生什么?", a: "依次走 embedding → chunk → 向量索引 → 概念抽取 → 公共节点对齐。整个流程通常 1-3 分钟,完成后可在「我的」页查看新增的私有节点。" },

  { cat: "data", q: "数据会被用来训练模型吗?", a: "不会。默认 NO,且我们无法改写这条策略(写入合同)。设置中有「把我的 chat 用于改进 Weavr」开关,默认关闭——只有你主动打开后,我们才会对该会话做匿名化抽样用于评估,绝不用于训练第三方模型。" },
  { cat: "data", q: "数据存在哪里?", a: "Supabase Singapore region(ap-southeast-1)。备份每小时一次,保留 30 天。文件加密(AES-256 at rest)。" },
  { cat: "data", q: "怎么导出数据 / 删除账号?", a: "设置 → 导入导出 → 一键导出全部数据为 ZIP(chats + 私有节点 + uploads + activity log)。账号删除在设置 → 隐私,30 天内可恢复,之后永久清除。" },
  { cat: "data", q: "怎么联系支持 / 报 bug?", a: "右下角 Tweaks 旁的「反馈」按钮,或邮件 support@nodeidea.app。Pro 用户优先响应(<24 小时),Studio < 4 小时。" },

  { cat: "models", q: "chat 用什么模型?我能选吗?", a: "Free:Gemini Flash-Lite(锁定)。Pro:可选 Claude Sonnet 4.5 / GPT-5 / Gemini Pro。每次对话顶部可切换。默认会根据问题复杂度自动路由。" },
  { cat: "models", q: "意图路由是怎么工作的?", a: "C1a 路由器先用规则(命令式 prompt / 节点引用 / 显式 mode 标签)判定,无法判定时回退到一个 small LLM 做分类。设置 → Labs 里可强制「Always LLM」或「Rules only」用于调试。" },
  { cat: "models", q: "为什么有时回答里会出现 [[节点引用]]?", a: "意味着模型在 retrieval-augmented 上下文中用到了该公共节点。点 chip 跳到节点本体可验证回答的依据。" },

  { cat: "billing", q: "能随时取消吗?", a: "可以。取消后当前周期内仍可使用,周期结束自动转为 Free。所有数据保留,可随时续费恢复。" },
  { cat: "billing", q: "支持哪些付款方式?", a: "信用卡 / 借记卡(Stripe)· 支付宝 · 微信支付。年付支持开票。" },
  { cat: "billing", q: "学生折扣?", a: "通过 SheerID 或 .edu 邮箱验证即可享 Pro 50% 折扣,每年验证一次。" },
  { cat: "billing", q: "退款政策?", a: "Pro/Studio 月付不退;首次年付订阅 7 天内可全额退款。Token Pack 一经购买不退。" },
];

function FAQPage({ tweaks }) {
  const [cat, setCat] = useStateF("all");
  const [q, setQ] = useStateF("");
  const filtered = QUESTIONS.filter(it =>
    (cat === "all" || it.cat === cat) &&
    (q === "" || it.q.toLowerCase().includes(q.toLowerCase()) || it.a.toLowerCase().includes(q.toLowerCase()))
  );

  return (
    <div className="subpage faq-page page-fade">
      <div className="mesh-bg" />
      <section className="container">
        <div className="subpage-hero">
          <span className="eyebrow">常见问题</span>
          <h1 className="h2" style={{ marginTop: 14 }}>常见问题</h1>
          <p className="lead">关于 Nodeidea 怎么用、数据怎么存、模型怎么选、怎么付费。找不到答案?写信 support@nodeidea.app。</p>
          <div className="h-search" style={{ maxWidth: 480, margin: "28px auto 0" }}>
            <Ic.Search />
            <input placeholder="搜索常见问题…" value={q} onChange={e => setQ(e.target.value)} />
            {q && <button onClick={() => setQ("")} style={{ background: "transparent", border: "none", color: "var(--text-dim)" }}>×</button>}
          </div>
        </div>

        <div className="faq-tabs">
          {Object.entries(FAQ_DATA).map(([k, label]) => (
            <button key={k} className={cat === k ? "active" : ""} onClick={() => setCat(k)}>
              {label}
              <span style={{ marginLeft: 8, color: "var(--text-faint)", fontFamily: "var(--font-mono)", fontSize: 11 }}>
                {k === "all" ? QUESTIONS.length : QUESTIONS.filter(x => x.cat === k).length}
              </span>
            </button>
          ))}
        </div>

        <div className="faq-list">
          {filtered.length === 0 && (
            <div style={{ textAlign: "center", padding: 80, color: "var(--text-dim)" }}>
              没找到匹配的问题。试试改改关键词,或写信给我们。
            </div>
          )}
          {filtered.map((it, i) => (
            <details key={it.q} open={i === 0 && q === ""}>
              <summary>
                <span>{it.q}</span>
                <span className="ctrl"><Ic.Plus /></span>
              </summary>
              <div className="body">{it.a}</div>
            </details>
          ))}
        </div>

        {/* still need help */}
        <div className="bottom-cta" style={{ marginTop: 100, padding: "60px 32px" }}>
          <h2 className="h3" style={{ maxWidth: 480, margin: "0 auto" }}>没找到答案?</h2>
          <p className="lead" style={{ margin: "12px auto 0" }}>给我们写信,通常 24 小时内回复。</p>
          <div className="cta-row" style={{ marginTop: 28 }}>
            <button className="btn btn-ghost">support@nodeidea.app</button>
            <button className="btn btn-primary">提交 bug</button>
          </div>
        </div>
      </section>
    </div>
  );
}

window.FAQPage = FAQPage;
