#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""DeepSeek Search 情报 → 自包含 HTML 日报
用法：python intel_ds_digest.py 20261016
"""
import csv
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输出-工作类'
V = os.path.join(W, '数据/market_intel/v01')
day = sys.argv[1]
rows = list(csv.DictReader(open(os.path.join(V, 'ds_search_%s.csv' % day), encoding='utf-8-sig')))
sm = json.load(open(os.path.join(V, 'ds_search_%s_summary.json' % day), encoding='utf-8'))
wl = json.load(open(os.path.join(V, 'watchlist_v2.json'), encoding='utf-8'))['items']
LAYER = {x['名称']: x.get('层', '行业龙头') for x in wl}
COMP = {'诺唯赞', '翌圣生物', '全式金', '菲鹏生物', '迈迪安', '宝生物', '赛默飞', '罗氏诊断'}

for r in rows:
    r['层级'] = ('竞品' if r['品牌/主体'] in COMP else
                 '招投标' if '招投标' in r['品牌/主体'] else LAYER.get(r['品牌/主体'], '其他'))

groups = [('客户相关', ['客户']), ('行业龙头/同赛道', ['行业龙头', '同赛道厂商']), ('竞品动态', ['竞品']),
          ('招投标（二级来源）', ['招投标']), ('其他', ['其他'])]


def table(rs):
    if not rs:
        return '<p class="empty">本窗口无新增</p>'
    out = ['<table><thead><tr><th style="width:9%">日期</th><th style="width:10%">事件</th>'
           '<th style="width:14%">主体</th><th>标题</th><th style="width:9%">相关度</th>'
           '<th style="width:13%">信源</th></tr></thead><tbody>']
    for r in rs:
        out.append('<tr><td>%s</td><td><span class="tag">%s</span></td><td>%s</td>'
                   '<td><a href="%s" target="_blank" rel="noopener">%s</a></td>'
                   '<td class="n">%s</td><td>%s</td></tr>' % (
                       r['发布日期'], r['事件类型'], r['品牌/主体'], r['URL'], r['标题'],
                       r['相关度'], r['信源']))
    out.append('</tbody></table>')
    return ''.join(out)


secs = []
for title, keys in groups:
    rs = [r for r in rows if r['层级'] in keys]
    rs.sort(key=lambda x: -float(x['相关度'] or 0))
    secs.append('<div class="card"><h2>%s <span>%d 条</span></h2>%s</div>' % (title, len(rs), table(rs)))

health = ''.join('<tr><td>%s</td><td class="n">%s</td><td class="n">%s</td><td>%s</td></tr>' % (
    h['实体'], h['返回'], h['保留'], h['状态']) for h in sm['health'])

page = """<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>行业情报 · DeepSeek Search · %(day)s</title><style>
*{box-sizing:border-box}body{margin:0;background:#f4f6fa;font-family:-apple-system,"PingFang SC",sans-serif;color:#1b2430;font-size:13px;line-height:1.6}
.wrap{max-width:1180px;margin:0 auto;padding:0 18px 36px}
h1{font-size:20px;margin:14px 0 4px}.meta{color:#5f6b7a;font-size:12.2px;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:9px;padding:10px 12px}
.kpi .k b{display:block;font-size:21px;color:#1852B6}.kpi .k span{font-size:11.3px;color:#6b7684}
.card{background:#fff;border:1px solid #e3e8f1;border-radius:10px;padding:13px 15px;margin-bottom:13px}
.card h2{font-size:14.5px;margin:0 0 9px;padding-left:9px;border-left:3px solid #1F4E79}
.card h2 span{font-size:11px;color:#8a94a3;font-weight:600}
table{width:100%%;border-collapse:collapse;font-size:11.9px}
th{background:#1F4E79;color:#fff;padding:6px 7px;text-align:left}
td{padding:5px 7px;border-bottom:1px solid #eef1f6;vertical-align:top}
td.n{text-align:right;font-variant-numeric:tabular-nums}
a{color:#1852B6;text-decoration:none}a:hover{text-decoration:underline}
.tag{background:#E8F0FE;color:#1852B6;border-radius:4px;padding:1px 6px;font-size:10.8px;white-space:nowrap}
.empty{color:#8a94a3;font-size:12px;margin:4px 0}
.warn{background:#FFF6E5;border:1px solid #F3D9A6;border-radius:8px;padding:9px 12px;font-size:12.2px}
@media(max-width:900px){.kpi{grid-template-columns:1fr 1fr}}
</style></head><body><div class="wrap">
<h1>行业情报日报 · DeepSeek Search 源</h1>
<div class="meta">目标日 %(day)s ｜时间窗 %(w0)s ~ %(w1)s ｜采集 %(queries)s 次查询 / 返回 %(ret)s 条 / 入库 %(k)d 条 ｜生成于 2026-10-17</div>
<div class="kpi">
<div class="k"><b>%(k)d</b><span>入库条目（有 URL + 有日期）</span></div>
<div class="k"><b>%(queries)d</b><span>查询次数（QPS≤5）</span></div>
<div class="k"><b>%(conv).0f%%</b><span>保留率（入库/返回）</span></div>
<div class="k"><b>5 元</b><span>本次估算成本（每千次 5 元）</span></div>
</div>
%(secs)s
<div class="card"><h2>信源健康度 <span>逐查询记录，不静默丢数据</span></h2>
<table><thead><tr><th>实体/主题</th><th style="text-align:right">返回</th><th style="text-align:right">保留</th><th>状态</th></tr></thead>
<tbody>%(health)s</tbody></table></div>
<div class="card"><h2>口径与边界</h2><div class="warn">
<ul style="margin:4px 0 0 18px;padding:0">
<li>检索源为 <b>DeepSeek 自研搜索引擎</b>（/v1/tools/search），非人工审校；每条均带原始 URL，可二次核验；</li>
<li>主体类查询相关度普遍 0.5–1.0，招投标 1.5–1.8 → <b>阈值分类设定</b>（主体 0.5 / 招投标 1.2），并要求主体名出现在标题或摘要中，防假关联；</li>
<li>日期取网页发布日；缺日期不入库；同一标题跨来源去重；</li>
<li>招投标为<b>二级来源</b>，只作线索，投标前须回原始公告核对；</li>
<li>窗口：每日默认回看 3 天（主体新闻稀疏，T-1 单日常常为空）。</li>
</ul></div></div>
%(footer)s
</div></body></html>""" % {
    'day': day, 'w0': sm['window'][0], 'w1': sm['window'][1],
    'queries': len(sm['health']), 'ret': sum(h['返回'] for h in sm['health']),
    'k': len(rows), 'conv': 100.0 * len(rows) / max(1, sum(h['返回'] for h in sm['health'])),
    'secs': ''.join(secs), 'health': health, 'footer': '__F__',
}
page = BK.inject(page, theme='dark', tag='行业情报 · DeepSeek Search',
                 footer_extra='内部资料 · 每条带原始链接，可二次核验')
page = page.replace('__F__', '')
out = os.path.join(W, '销售分析', '行业情报_DeepSeekSearch_%s.html' % day)
open(out, 'w', encoding='utf-8').write(page)
print('✅', out, '%.0f KB' % (len(page.encode()) / 1024))
