#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""把飞书 MCP 活动（9 月）落成本地基础数据集，供「拜访与活动」下钻用。

来源：数据/daily_activities_mcp.json（每日管道刷新，今日 21:07）
输出：数据/activities_feishu.json
  items[].{id,date,submitted_by,sales,customer,channel,type,src,text}
  —— 刻意用与 数据/activities/_index.json **同形状**的字段名，
     这样 /api/visit/stats 的聚合与权限过滤可以原样复用。

channel 推断：活动名称 + 描述文本关键词；两条线索冲突或全无 → unknown（不硬猜）。
  必须显式回传「可判定比例」，避免把「未标」静默算进任一侧。
"""
import io
import json
import os
import re
import sys
import time
from collections import Counter

ROOT = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
SRC = os.path.join(ROOT, '数据', 'daily_activities_mcp.json')
OUT = os.path.join(ROOT, '数据', 'activities_feishu.json')

MONTHS = sys.argv[1:] if len(sys.argv) > 1 else ['2026-09']

OFFLINE = ['拜访', '上门', '来访', '到访', '面谈', '当面', '请客', '吃饭', '出差', '驻场', '现场',
           '参观', '考察', '走访', '送样', '带样', '到场']
ONLINE = ['电话', '致电', '微信', '线上', '腾讯会议', '视频', 'zoom', 'Zoom', '邮件', '远程',
          '钉钉', '语音', '网络会议']


def infer(name, desc):
    t = '%s %s' % (name or '', (desc or '')[:400])
    o = [w for w in OFFLINE if w in t]
    n = [w for w in ONLINE if w in t]
    if o and not n:
        return 'offline', o[:3]
    if n and not o:
        return 'online', n[:3]
    if o and n:
        return 'unknown', (o[:2] + n[:2])      # 冲突 → 不硬猜
    return 'unknown', []


def main():
    raw = json.load(io.open(SRC, encoding='utf-8'))
    items = raw.get('items') or []
    print('源：%s（updated %s，共 %d 条）' % (os.path.basename(SRC), raw.get('updated'), len(items)))

    out, cnt = [], Counter()
    for x in items:
        d = (x.get('start_time') or '')[:10]
        if len(d) < 7 or d[:7] not in MONTHS:
            continue
        cust = x.get('field_5f20fc')
        cust = (cust.get('label') if isinstance(cust, dict) else cust) or ''
        own = x.get('owner') or {}
        name = (own.get('name_cn') or own.get('name_en') or '').strip() if isinstance(own, dict) else str(own or '')
        typ = (x.get('name') or '').strip()
        desc = (x.get('field_b99055') or '').strip()
        ch, ev = infer(typ, desc)
        cnt[ch] += 1
        out.append({
            'id': 'FS%d' % (x.get('work_item_id') or abs(hash(d + typ + cust)) % 10 ** 9),
            'date': d,
            'submitted_by': name,
            'sales': name,
            'customer': cust.strip(),
            'channel': ch,
            'channel_ev': ev,
            'type': typ,
            'src': 'feishu',
            'text': desc[:1500],
        })

    out.sort(key=lambda r: (r['date'], r['id']))
    tot = len(out)
    payload = {'source': 'feishu_mcp', 'generated': time.strftime('%Y-%m-%d %H:%M:%S'),
               'src_file': os.path.basename(SRC), 'src_updated': raw.get('updated'),
               'months': MONTHS, 'total': tot,
               'channel_breakdown': {'offline': cnt['offline'], 'online': cnt['online'], 'unknown': cnt['unknown']},
               'note': '飞书历史活动只作只读基础数据；channel 由文本推断，unknown 不计入线下/线上',
               'items': out}
    io.open(OUT, 'w', encoding='utf-8').write(json.dumps(payload, ensure_ascii=False, indent=0))

    print('输出：%s（%.1f KB）' % (OUT, os.path.getsize(OUT) / 1024.0))
    print('  月份 %s ｜ 条数 %d' % (MONTHS, tot))
    print('  可判定 %d（%.1f%%）｜ 未标 %d（%.1f%%）'
          % (cnt['offline'] + cnt['online'], (cnt['offline'] + cnt['online']) * 100.0 / max(tot, 1),
             cnt['unknown'], cnt['unknown'] * 100.0 / max(tot, 1)))
    print('  线下 %d ｜ 线上 %d ｜ 未标 %d' % (cnt['offline'], cnt['online'], cnt['unknown']))
    print('  归属人 %d 位 ｜ 客户 %d 家'
          % (len({r['submitted_by'] for r in out}), len({r['customer'] for r in out if r['customer']})))
    print('  样例：', json.dumps({k: v for k, v in out[0].items() if k != 'text'}, ensure_ascii=False) if out else '—')


main()
