#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""CRM 客户表归一化补全（工作台「客户」Tab 依赖的友好字段）。

背景（2026-10-15 实测）：
  数据/mcp_customers.json 是飞书客户表的原始导出，行里只有 field_* 原始键
  （field_c3224b=集团 / field_5ed7ab=部门 / field_17186c=等级 / field_c8e80d=类型），
  而前端 renderCustomers() 读的是 c.group / c.dept / c.level / c.ctype / c.amount / c.contacts。
  → 「集团」与「区域」维度全部落进「未知」桶、金额恒为 0（生凌集团 4 主体因此完全没被归集）。

本脚本按行补：group（权威映射优先）/ dept / ctype / level / amount / sales_2026 / orders / contacts。
金额只来自 _key_customers.json 的既有值（不重算、不估算），匹配不上留空并计数。

用法：env -u PYTHONPATH /opt/homebrew/bin/python3 脚本/enrich_mcp_customers.py [--dry]
"""
import io
import json
import os
import shutil
import sys
from datetime import datetime

W = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
CRM = W + '/数据/mcp_customers.json'
KEY = W + '/数据/pricing/_key_customers.json'
DM = W + '/数据/diag_mappings.json'
BK = W + '/数据/backup'
DRY = '--dry' in sys.argv
TS = datetime.now().strftime('%Y%m%d_%H%M%S')

crm = json.load(io.open(CRM, encoding='utf-8'))
key_rows = json.load(io.open(KEY, encoding='utf-8'))
gmap = {str(k).strip(): str(v).strip() for k, v in
        (json.load(io.open(DM, encoding='utf-8')).get('cust_to_group') or {}).items()}
by_name = {str(r.get('name') or '').strip(): r for r in key_rows}

NOISE = {'', '无', '暂无', '-', '/', '／', '`', '1', '0', '否', '未知', '待定', '其他', 'n/a', 'na', 'none', 'nan'}
def clean(v):
    s = str(v or '').strip()
    return '' if s.lower() in NOISE or s in NOISE else s

def label(f):
    v = f if isinstance(f, dict) else {}
    return clean(v.get('label') or v.get('name') or '')

n = {'group': 0, 'group_from_crm': 0, 'dept': 0, 'level': 0, 'ctype': 0, 'amount': 0, 'contacts': 0, 'unmatched': 0}
for c in crm.get('customers', []):
    name = str(c.get('name') or '').strip()
    g = gmap.get(name, '') or clean(c.get('field_c3224b'))
    if g and not gmap.get(name):
        n['group_from_crm'] += 1
    if g:
        c['group'] = g
        c['group_name'] = g
        n['group'] += 1
    d = label(c.get('field_5ed7ab'))
    if d:
        c['dept'] = d
        n['dept'] += 1
    lv = label(c.get('field_17186c'))
    if lv:
        c['level'] = lv
        n['level'] += 1
    ct = label(c.get('field_c8e80d'))
    if ct:
        c['ctype'] = ct
        n['ctype'] += 1
    k = by_name.get(name)
    if k:
        c['amount'] = k.get('total') or 0
        c['sales_2024'] = k.get('sales_2024')
        c['sales_2025'] = k.get('sales_2025')
        c['sales_2026'] = k.get('sales_2026')
        c['orders'] = k.get('orders')
        c['contacts'] = (k.get('contacts') if isinstance(k.get('contacts'), int)
                         else len(k.get('contacts') or []))
        c['decision_url'] = k.get('decision_url') or ''
        n['amount'] += 1
        n['contacts'] += 1
    else:
        c.setdefault('amount', 0)
        c.setdefault('contacts', 0)
        n['unmatched'] += 1
    c['is_group_row'] = False          # CRM 是实体表，无汇总行

print('═' * 88)
print('CRM 客户表归一化补全')
print('═' * 88)
print('  行数 %d ｜ 有 group %d（其中由 CRM 原字段兜底 %d）｜ dept %d ｜ 等级 %d ｜ 类型 %d'
      % (len(crm.get('customers', [])), n['group'], n['group_from_crm'], n['dept'], n['level'], n['ctype']))
print('  金额/联系人：命中 _key_customers %d 行 ｜ 未命中（无历史成交记录）%d 行' % (n['amount'], n['unmatched']))
sl = [c for c in crm['customers'] if '生凌' in str(c.get('name'))]
print('  生凌系 %d 行：' % len(sl))
for c in sl:
    print('     %-34s group=%-12s dept=%-16s amount=%12s 2026=%s' % (
        c.get('name'), c.get('group'), c.get('dept'), c.get('amount'), c.get('sales_2026')))
print('  集团去重：%d' % len({c['group'] for c in crm['customers'] if c.get('group')}))
for g, cnt in sorted(((g, sum(1 for c in crm['customers'] if c.get('group') == g))
                      for g in {c['group'] for c in crm['customers'] if c.get('group')}), key=lambda x: -x[1])[:8]:
    print('     %-22s %d 家' % (g, cnt))

if DRY:
    print('\n（--dry 模式，未写盘）')
    sys.exit(0)
os.makedirs(BK, exist_ok=True)
shutil.copy2(CRM, '%s/mcp_customers.json.bak-%s' % (BK, TS))
with io.open(CRM, 'w', encoding='utf-8') as f:
    json.dump(crm, f, ensure_ascii=False)
print('\n  ✅ 已写 %s（备份 → 数据/backup/mcp_customers.json.bak-%s）' % (CRM.split('/')[-1], TS))
