#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""activities_feishu.json 构建器（拜访视图数据源）— 从 daily_activities_mcp.json 派生。

背景（2026-10-22）：
  `脚本/pull_activities_mcp.py` 走的是 `curl --resolve project.feishu.cn:443:<写死IP>` + 60s 超时，
  且每月用一次「整月无 LIMIT + session_id 翻页」的大查询。写死 IP 的路由一旦变慢，
  整月首查就 60s 超时 → 脚本抛 TimeoutExpired，**activities_feishu.json 完全得不到更新**。
  实测同一月份 MQL 走 urllib(R.mcp_call) 仅 1.3s，瓶颈在 --resolve 那条链路，不在 MQL。

本脚本改为派生式：直接消费 `数据/_pull_segmented.py activities --months 4` 已拉好的
  daily_activities_mcp.json（同为 2026-07-01 起的活动全量，7/7 字段齐全），
  不再重复打 MCP，口径天然与日更文件一致。

字段对应（MQL key → 输出）：
  name→名称 / field_76654e→活动类型 / field_5f20fc→活动关联客户 / field_5ed7ab→跟进部门
  owner→创建者 / start_time→创建时间 / field_b99055→活动描述 / work_item_id→id

用法：python3 脚本/build_activities_feishu.py [daily_activities_mcp.json]
输出：数据/activities_feishu.json（schema 与旧 pull_activities_mcp.py 完全一致）
"""
import io
import json
import os
import sys
import time
from collections import Counter

W = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
SRC = sys.argv[1] if len(sys.argv) > 1 else os.path.join(W, '数据', 'daily_activities_mcp.json')
OUT = os.path.join(W, '数据', 'activities_feishu.json')
MIN_OK = 4000            # 安全闸：低于此条数不覆盖正式文件

OWNER_MERGE = {'张立娅': '刘子研', '黄明月': '刘子研'}   # 离职归并，与 cron 刷新 Step 1/3a 同口径
TYPE_MAP = {
    '线下拜访': 'offline',
    '线上跟进': 'online',
    '协同拜访': 'joint',
    '陌拜(指线索及客户板块均无客户信息，属于初次开发)': 'cold',
    '陌拜': 'cold',
}


def label(v):
    """{key,label} / user_value / 裸值 → 纯文本。"""
    if v is None:
        return ''
    if isinstance(v, dict):
        if v.get('label'):
            return str(v['label']).strip()
        if v.get('name_cn') or v.get('name_en'):
            return str(v.get('name_cn') or v.get('name_en')).strip()
        return ''
    return str(v).strip()


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

    items, cnt, months = [], Counter(), set()
    for r in rows:
        d = (r.get('start_time') or '')[:10]
        if not d:
            continue
        months.add(d[:7])
        who = OWNER_MERGE.get(label(r.get('owner')), label(r.get('owner')))
        atype = label(r.get('field_76654e'))
        ch = TYPE_MAP.get(atype, 'none')
        items.append({
            'id': 'FS%s' % (r.get('work_item_id') or ''),
            'date': d,
            'submitted_by': who,
            'sales': who,
            'customer': label(r.get('field_5f20fc')),
            'channel': ch,
            'atype': atype,
            'dept_raw': label(r.get('field_5ed7ab')),
            'type': (r.get('name') or '').strip(),
            'src': 'feishu',
            'text': (r.get('field_b99055') or '')[:1500],
        })
        cnt[ch] += 1

    items.sort(key=lambda x: (x['date'], x['id']), reverse=True)
    tot = len(items)
    MONTHS = sorted(months)
    payload = {
        'source': 'feishu_mcp_activity_type',
        'generated': time.strftime('%Y-%m-%d %H:%M:%S'),
        'months': MONTHS,
        'total': tot,
        'channel_breakdown': {k: cnt[k] for k in ('offline', 'online', 'cold', 'joint', 'none')},
        'type_raw': dict(Counter(x['atype'] or '(未填)' for x in items)),
        'owner_merge': OWNER_MERGE,
        'note': '活动形式取自飞书「活动类型」字段（field_76654e），非文本推断；陌拜/协同拜访归线下；'
                '本文件由 build_activities_feishu.py 从 daily_activities_mcp.json 派生',
        'items': items,
    }

    tmp = OUT + '.tmp'
    with io.open(tmp, 'w', encoding='utf-8') as f:
        f.write(json.dumps(payload, ensure_ascii=False, indent=0))
    if tot < MIN_OK:
        print('  🔴 仅 %d 条（基准 ≥%d），不覆盖正式文件，保留 %s' % (tot, MIN_OK, tmp))
        sys.exit(1)
    os.replace(tmp, OUT)
    print('  渠道：线下 %d ｜ 线上 %d ｜ 陌拜 %d ｜ 协同 %d ｜ 未填 %d'
          % (cnt['offline'], cnt['online'], cnt['cold'], cnt['joint'], cnt['none']))
    print('  ✅ 写入 %s: %d 条 ｜ 月份 %s' % (OUT, tot, ','.join(MONTHS)))


if __name__ == '__main__':
    main()
