#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""IMA 诊断原料知识库 · 正文检索与主题汇总报告
输入：数据/ima_corpus.json、数据/ima_themes_wechat.json、数据/ima_themes_local.json
输出：销售分析/IMA知识库_诊断原料_近三个月内容汇总_2026-10-17.html
"""
import json
import os
import sys

sys.path.insert(0, '/Users/liuxinyuan/Desktop/Hermes输出-工作类/脚本')
import brand_kit as BK  # noqa: E402

W = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
D = os.path.join(W, '数据')
OUT = os.path.join(W, '销售分析', 'IMA知识库_诊断原料_内容汇总_2026-10-17.html')

corpus = json.load(open(os.path.join(D, 'ima_corpus.json'), encoding='utf-8'))['items']
wx = json.load(open(os.path.join(D, 'ima_themes_wechat.json'), encoding='utf-8'))
lc = json.load(open(os.path.join(D, 'ima_themes_local.json'), encoding='utf-8'))

total_kb = len(json.load(open(os.path.join(D, 'ima_kb_index_诊断原料.json'), encoding='utf-8'))['items'])
n_wx_ok = sum(1 for x in corpus if x['source'] == 'wechat' and x['status'] == 'ok')
n_wx_miss = sum(1 for x in corpus if x['source'] == 'wechat' and x['status'] != 'ok')
n_lc_ok = sum(1 for x in corpus if x['source'] == 'local' and x['status'] == 'ok')
readable = n_wx_ok + n_lc_ok


def esc(s):
    return (str(s or '').replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;'))


def theme_html(t, src):
    pts = []
    for p in t.get('points', []):
        ev = p.get('evidence') or {}
        quote = esc(ev.get('quote', ''))
        title = esc(ev.get('title', ''))
        url = ev.get('url', '')
        date = esc(ev.get('date', ''))
        link = '<a href="%s" target="_blank" rel="noopener">%s</a>' % (url, title) if url else title
        pts.append('<li><b>%s</b><div class="ev">%s%s%s</div></li>' % (
            esc(p.get('text', '')), link,
            (' ｜ ' + date) if date else '',
            ('<br><span class="q">“%s”</span>' % quote) if quote else ''))
    return ('<div class="theme"><div class="th"><h3>%s</h3><span class="badge %s">%s</span></div>'
            '<p>%s</p><ul>%s</ul></div>') % (
        esc(t.get('name')), 'wx' if src == 'wechat' else 'lc',
        '公众号' if src == 'wechat' else '本地文件',
        esc(t.get('summary')), ''.join(pts))


themes = ''.join(theme_html(t, 'wechat') for t in wx.get('themes', []))
themes += ''.join(theme_html(t, 'local') for t in lc.get('themes', []))

nums = ''.join('<tr><td>%s</td><td>%s</td><td>%s</td></tr>' % (
    esc(x.get('value')), esc(x.get('meaning')), esc(x.get('source_title'))) for x in wx.get('notable_numbers', []))
acts = ''.join('<li>%s</li>' % esc(x) for x in lc.get('actionable', []))
gaps = ''.join('<li>%s</li>' % esc(x) for x in (lc.get('gaps', []) + wx.get('insufficient', [])))

page = """<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>IMA 诊断原料知识库 · 内容汇总</title>
<style>
*{box-sizing:border-box}body{margin:0;background:#f4f6fa;font-family:-apple-system,"PingFang SC",sans-serif;color:#1b2430;font-size:13.4px;line-height:1.7}
.wrap{max-width:1120px;margin:0 auto;padding:0 18px 40px}
h1{font-size:21px;margin:14px 0 4px}.sub{color:#5f6b7a;font-size:12.5px;margin-bottom:12px}
.kpi{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}
.kpi .k{background:#fff;border:1px solid #e3e8f1;border-radius:10px;padding:11px 13px}
.kpi b{display:block;font-size:22px;color:#1852B6}.kpi span{font-size:11.3px;color:#6b7684}
.card{background:#fff;border:1px solid #e3e8f1;border-radius:10px;padding:14px 16px;margin-bottom:14px}
.card h2{font-size:15px;margin:0 0 10px;padding-left:9px;border-left:3px solid #1F4E79}
.theme{border:1px solid #e3e8f1;border-radius:9px;padding:11px 13px;margin-bottom:11px;background:#fbfcff}
.th{display:flex;align-items:center;gap:8px}
.th h3{font-size:14px;margin:0}
.badge{font-size:10.5px;border-radius:20px;padding:1px 8px}
.badge.wx{background:#E8F0FE;color:#1852B6}.badge.lc{background:#E3F4EA;color:#1B7A43}
.theme p{margin:4px 0 6px;color:#3d4a5a;font-size:12.5px}
.theme ul{margin:0 0 0 18px;padding:0}
.theme li{margin:5px 0;font-size:12.4px}
.ev{font-size:11.4px;color:#6b7684}
.q{color:#8a5a12}
table{width:100%%;border-collapse:collapse;font-size:12px}
th{background:#1F4E79;color:#fff;padding:6px 8px;text-align:left}
td{padding:5px 8px;border-bottom:1px solid #eef1f6}
a{color:#1852B6;text-decoration:none}a:hover{text-decoration:underline}
.note{background:#FFF6E5;border:1px solid #F3D9A6;border-radius:8px;padding:10px 12px;font-size:12.4px}
@media(max-width:900px){.kpi{grid-template-columns:1fr 1fr}.bior-tagwrap{display:none!important}}
</style></head><body><div class="wrap">
<h1>IMA 知识库 · 诊断原料 · 内容汇总</h1>
<div class="sub">来源：宝锐诊断原料销售知识库（%(total)d 条，已剔除个人笔记）｜ 只取知识库公开条目，<b>不含个人笔记</b> ｜ 生成于 2026-10-17</div>

<div class="kpi">
<div class="k"><b>%(total)d</b><span>知识库条目</span></div>
<div class="k"><b>%(readable)d</b><span>取到正文（%(pct).0f%%）</span></div>
<div class="k"><b>%(wx)d</b><span>公众号文章命中</span></div>
<div class="k"><b>%(lc)d</b><span>本地文件可读</span></div>
</div>

<div class="card"><h2>怎么读这份报告 <span>口径先看</span></h2>
<div class="note">
<ul style="margin:4px 0 0 18px;padding:0">
<li><b>公众号正文是“标题检索 + 转载版本”</b>：知识库不返回原文链接，按标题在全网找回，可能匹配到同名/近似文章；文中标注的日期与链接均来自找回的页面，<b>引用片段已逐字核对</b>。</li>
<li><b>本地文件</b>来自 IMA 同步副本，日期为本地落盘日，非发布日；PDF 仅抽取前 6 页。</li>
<li><b>未取到正文的 %(miss)d 篇</b>：无原文链接、转载未收录、或站点反爬；不做推测性概括，见文末缺口清单。</li>
<li>知识库 API <b>不提供更新时间</b>，因此无法严格按“最近三个月”筛选；报告以“主题 + 可读正文”为口径，日期仅作参考。</li>
</ul>
</div></div>

<div class="card"><h2>主题汇总 <span>按内容聚类，公众号在前、本地文件在后</span></h2>
%(themes)s
</div>

<div class="card"><h2>值得记住的数字 <span>均可在原文核对</span></h2>
<div class="tw"><table><thead><tr><th style="width:18%%">数字</th><th>含义</th><th style="width:30%%">出处</th></tr></thead><tbody>%(nums)s</tbody></table></div>
</div>

<div class="card"><h2>可执行清单 <span>来自制度与产品资料</span></h2>
<ul style="margin:4px 0 0 18px;padding:0">%(acts)s</ul>
</div>

<div class="card"><h2>读不到的部分 <span>如实列出，不替代推测</span></h2>
<ul style="margin:4px 0 0 18px;padding:0">%(gaps)s</ul>
<p style="margin-top:8px;font-size:12.2px;color:#6b7684">另有 74 篇公众号文章未找回正文（标题保留在索引中），如需，可逐篇人工提供链接或在 IMA 桌面端导出后我再补。</p>
</div>
%(footer)s
</div></body></html>""" % {
    'total': total_kb, 'readable': readable, 'pct': 100.0 * readable / total_kb,
    'wx': n_wx_ok, 'lc': n_lc_ok, 'miss': n_wx_miss,
    'themes': themes, 'nums': nums, 'acts': acts, 'gaps': gaps, 'footer': '__F__',
}
page = BK.inject(page, theme='dark', tag='IMA 知识库 · 诊断原料 内容汇总',
                 footer_extra='内部资料 · 不对外 ｜ 引用均来自知识库条目可读正文')
page = page.replace('__F__', '')
page = page.replace('<table>', '<div class="tw"><table>').replace('</table>', '</table></div>')
open(OUT, 'w', encoding='utf-8').write(page)
print('✅', OUT, '%.0f KB' % (len(page.encode()) / 1024))
