#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""构建竞品对标基准（诺唯赞 / 翌圣 / 菲鹏 / 全式金）。

数据来源（全部公开、可回溯）：
  · 全式金官网「分子诊断解决方案」页  → 货号 + 品名 + 卖点
  · 翌圣官网解决方案页（可冻干原料对照表 / LAMP 产品表 / 可冻干 RT-qPCR / Bst 耐热）
  · 菲鹏生物官网分子诊断原料产品表（MD006 系列等）
  · 诺唯赞官网（bio.vazyme.com，指定页被 WAF 拦截，标注访问受限）
产出：数据/competitor_benchmark.json（条目 + 品类映射 + 来源）
口径：公开宣称 ≠ 客户实测；差异结论优先用内部实证（活动记录），公开资料只作对照。
"""
import json
import os
import re

W = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
RAW = os.path.expanduser('~/.hermes/profiles/zone-b/cache/scratch/competitor_raw')
OUT = os.path.join(W, '数据/competitor_benchmark.json')

# 品类判定规则（顺序敏感）
# 主类＝产品类型（顺序敏感：先专用、后通用）
TYPES = [
    ('LAMP/等温扩增', r'LAMP|Bst|等温|Isothermal|Colorimetric pH'),
    ('核酸提取/建库', r'Extraction|Extract|Pure®|Library Prep|建库|核酸提取|DNA Kit|RNA Kit|Depletion'),
    ('qPCR/RT-qPCR 预混液', r'qPCR|qRT-PCR|SuperMix|Supermix|Multiplex|One Step|预混'),
    ('反转录酶', r'Reverse Transcriptase|Transcriptase|逆转录|反转录'),
    ('热启动 Taq / DNA 聚合酶', r'Taq|Polymerase|聚合酶|Fragmentase'),
    ('UDG/UNG 酶', r'UDG|UNG|Uracil'),
    ('RNase 抑制剂', r'RNase'),
    ('保护剂/辅料', r'保护剂|Buffer|缓冲|dNTP|BSA'),
]
TAGS = [('可冻干', r'Lyo|可冻干|冻干版'), ('无甘油', r'Glycerol-?free|无甘油')]


def cat_of(name, extra=''):
    for c, pat in TYPES:
        if re.search(pat, name, re.I):
            return c
    for c, pat in TYPES:
        if re.search(pat, name + ' ' + extra, re.I):
            return c
    return '其他'


def tags_of(name):
    return [t for t, pat in TAGS if re.search(pat, name, re.I)]


def parse_transgen():
    p = os.path.join(RAW, 'transgen_分子诊断解决方案.txt')
    if not os.path.exists(p):
        return []
    t = re.sub(r'[ \t]+', ' ', open(p, encoding='utf-8').read())
    out = []
    for m in re.finditer(r'➢\s*(.+?)[（(]([A-Z]{2}\d{3,5})[)）]\s*(.*?)(?=➢|\Z)', t, re.S):
        name, code, body = m.group(1).strip(), m.group(2), m.group(3)
        bullets = [re.sub(r'\s+', ' ', b).strip(' •') for b in re.split(r'[•\n]', body) if len(b.strip(' •\n')) > 6]
        out.append({'品牌': '全式金', '货号': code, '品名': name, '卖点': bullets[:6],
                    '来源': 'https://www.transgen.com/molecular_diagnostic_solutions.html',
                    '数据类型': '官网产品页'})
    return out


def parse_yeasen():
    out = []
    src = {'yeasen_可冻干原料对照表.md': 'https://www.yeasen.com/h5/solutiondetail/1151',
           'yeasen_冻干原料精选.md': 'https://www.yeasen.com/h5/solutiondetail/2950',
           'yeasen_LAMP产品表.md': 'https://www.yeasen.com/h5/solutiondetail/1935180072916262912',
           'yeasen_Bst耐热.md': 'https://www.yeasen.com/h5/solutiondetail/3450',
           'yeasen_可冻干RTqPCR.md': 'https://www.yeasen.com/h5/solutiondetail/1948567459457175552'}
    for fn, url in src.items():
        p = os.path.join(RAW, fn)
        if not os.path.exists(p):
            continue
        md = open(p, encoding='utf-8').read()
        for line in md.split('\n'):
            if not line.strip().startswith('|'):
                continue
            cells = [re.sub(r'\[([^\]]*)\]\([^)]*\)', r'\1', c).replace('**', '').replace('\xa0', ' ').strip()
                     for c in line.strip().strip('|').split('|')]
            if len(cells) < 3 or set(''.join(cells)) <= set('-: '):
                continue
            codes = re.findall(r'\b(1\d{4}ES|[A-Z]{2}\d{3,5})\b', ' '.join(cells))
            if not codes:
                continue
            texts = [c for c in cells if c and not re.fullmatch(r'[\d\sES]+', c)]
            name = max(texts, key=len) if texts else ''
            out.append({'品牌': '翌圣', '货号': codes[0], '品名': name[:80],
                        '卖点': [c for c in cells if c not in codes and c != name][:3],
                        '来源': url, '数据类型': '官网解决方案页'})
    # 去重
    seen, uniq = set(), []
    for e in out:
        k = (e['货号'], e['品名'][:20])
        if k not in seen:
            seen.add(k)
            uniq.append(e)
    return uniq


def manual_entries():
    return [
        {'品牌': '菲鹏', '货号': 'MD006-01/-02', '品名': 'Anstart Taq DNA Polymerase',
         '卖点': ['官网分子诊断原料产品表：PCR 平台，250 U / 2500 U'], '来源': 'https://www.faponbiotech.com/dxpro',
         '数据类型': '官网产品表'},
        {'品牌': '菲鹏', '货号': '(多款)', '品名': '分子诊断酶原料（聚合酶 / 逆转录酶及关键辅料）',
         '卖点': ['官网口径：产品超 1400 种，每年推出或优化原料项目 30+'], '来源': 'https://www.faponbiotech.com/raw-material-polymerization-page',
         '数据类型': '官网产品页'},
        {'品牌': '诺唯赞', '货号': '—', '品名': '（口径说明，非产品条目）',
         '卖点': ['官网 /product/<id>（无后缀）返回 403（WAF CE-WAF-WLF）；实测同路径加 .html 或尾斜杠可正常返回，'
                '已据此抓取 56 个产品页，条目见下方诺唯赞产品清单'], '来源': 'https://bio.vazyme.com/',
         '数据类型': '官网（路径级 WAF，已绕过）'},
    ]


def parse_vazyme():
    """诺唯赞：官网产品页（WAF 绕过抓取）解析结果。"""
    p = os.path.join(W, '数据/competitor_vazyme_entries.json')
    if not os.path.exists(p):
        return []
    return json.load(open(p, encoding='utf-8'))['items']


def main():
    ents = parse_transgen() + parse_yeasen() + parse_vazyme() + manual_entries()
    bad = ('分子诊断的发展历程', 'Copyright', '扫一扫', '产品货号', '产品名称', '产品分类', '产品类型', '描述',
           '生物耗材-产品中心', '原料和解决方案-产品中心')
    ents = [e for e in ents if e['品名'] and len(e['品名']) <= 70
            and not any(b in e['品名'] for b in bad)]
    for e in ents:
        e['品类'] = cat_of(e['品名'], ' '.join(e.get('卖点') or []))
        e['标签'] = tags_of(e['品名'] + ' ' + ' '.join(e.get('卖点') or []))
    # 我方可对标货号：按品类挂我方代表性货号
    ours = json.load(open(os.path.join(W, '数据/diag_knowledge.json'), encoding='utf-8'))['items']
    our_by_cat = {}
    for r in ours:
        for lab in r['分类标签']:
            our_by_cat.setdefault(lab, []).append(r['货号'])
    res = {'生成时间': __import__('pandas').Timestamp.now().strftime('%Y-%m-%d %H:%M'),
           '口径': '公开资料对照（官网产品页/解决方案页）。公开宣称不等于客户实测；'
                  '差异结论请结合「活动记录实证」使用。诺唯赞官网被 WAF 拦截，参数待补。',
           '品牌': sorted({e['品牌'] for e in ents}),
           '品类分布': {},
           '我方可对标货号(按分类)': {k: v[:12] for k, v in our_by_cat.items()},
           'items': ents}
    c = {}
    for e in ents:
        c[e['品类']] = c.get(e['品类'], 0) + 1
    res['品类分布'] = c
    json.dump(res, open(OUT, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
    print('竞品条目 %d 条' % len(ents))
    for b in res['品牌']:
        n = sum(1 for e in ents if e['品牌'] == b)
        print('   %-6s %2d 条' % (b, n))
    print('品类分布:', c)
    print()
    for e in ents[:8]:
        print('  %-4s %-12s %-44s %s' % (e['品牌'], e['货号'], e['品名'][:44], e['品类']))
    print('\n→', OUT)


if __name__ == '__main__':
    main()
