#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""实测活动录入接口（取 admin token 走真实 HTTP）"""
import json, os, time, urllib.request, urllib.error, io

BASE = 'http://127.0.0.1:8765'
AF = os.path.expanduser('~/Desktop/Hermes输出-工作类/数据/auth_sessions.json')
sess = json.load(open(AF, encoding='utf-8'))
tok = max(sess.items(), key=lambda kv: kv[1].get('expire_at', 0))[0]
print('  使用 token 前 12 位:', tok[:12], '｜ 用户:', sess[tok].get('name'), sess[tok].get('role'))


def req(path, data=None, method=None, ctype='application/json', raw=None):
    url = BASE + path
    headers = {'Authorization': 'Bearer ' + tok}
    body = None
    if raw is not None:
        body = raw
        headers['Content-Type'] = ctype
    elif data is not None:
        body = json.dumps(data, ensure_ascii=False).encode()
        headers['Content-Type'] = ctype
    r = urllib.request.Request(url, data=body, headers=headers, method=method)
    try:
        with urllib.request.urlopen(r, timeout=60) as resp:
            return resp.status, json.loads(resp.read().decode('utf-8'))
    except urllib.error.HTTPError as e:
        try:
            return e.code, json.loads(e.read().decode('utf-8'))
        except Exception:
            return e.code, {}


print('\n① GET /api/activity/orders?limit=5')
st, j = req('/api/activity/orders?limit=5')
print('   HTTP', st, '｜ total', j.get('total'))
for o in (j.get('orders') or [])[:3]:
    print('   ', o['no'], o['customer'][:24], o['date'], '测试单' if o['is_test'] else '标准', 'SKU', o['sku_count'])

first_no = (j.get('orders') or [{}])[0].get('no')
print('\n② GET /api/activity/order_skus?no=%s' % first_no)
st, j2 = req('/api/activity/order_skus?no=' + urllib.parse.quote(first_no))
print('   HTTP', st, '｜ 订单', (j2.get('order') or {}).get('customer', '')[:30], '｜ 货号数', len((j2.get('order') or {}).get('skus') or []))
for x in ((j2.get('order') or {}).get('skus') or [])[:3]:
    print('    -', x['sku'], '|', x['name'][:28], '| qty', x['qty'], '| 赠品' if x['gift'] else '')

print('\n③ POST /api/activity/attachment（multipart 上传测试）')
probe = '接口自测附件 %s\n' % time.strftime('%Y-%m-%d %H:%M:%S')
boundary = '----hermesprobe%s' % int(time.time())
parts = []
for k, v in (('activityId', 'ACTTEST_' + time.strftime('%Y%m%d%H%M%S')), ('sku', 'FM2181-4')):
    parts.append(('--%s\r\nContent-Disposition: form-data; name="%s"\r\n\r\n%s\r\n' % (boundary, k, v)).encode())
parts.append(('--%s\r\nContent-Disposition: form-data; name="file"; filename="自测附件.txt"\r\n'
              'Content-Type: text/plain\r\n\r\n%s\r\n' % (boundary, probe)).encode())
parts.append(('--%s--\r\n' % boundary).encode())
st, j3 = req('/api/activity/attachment', raw=b''.join(parts), ctype='multipart/form-data; boundary=%s' % boundary)
print('   HTTP', st, '｜ ok', j3.get('ok'), '｜ activityId', j3.get('activityId'))
att = (j3.get('files') or [{}])[0]
print('   文件:', att.get('name'), att.get('size'), 'B ｜ 云存储:', att.get('cloud_ok'), att.get('cloud_path'))
if att.get('err'):
    print('   err:', att.get('err')[:200])

print('\n④ POST /api/activity/submit（项目跟进，含订单+货号+附件）')
payload = {
    'type': '项目跟进', 'subtype': '', 'customer': (j2.get('order') or {}).get('customer', ''),
    'contact': '接口自测', 'date': time.strftime('%Y-%m-%d'), 'sales': sess[tok].get('name'),
    'need': '1. 全预混体系上机适配\n2. 要求 25℃ 常温稳定 18 个月\n3. 需要 NA 级残留证明',
    'params': [{'sku': 'FM2181-4', 'desc': '扩增 20min，灵敏度 1 copy/μL，批间 CV<5%'}],
    'test_order': {'no': first_no, 'customer': (j2.get('order') or {}).get('customer', ''),
                   'items': [{'sku': ((j2.get('order') or {}).get('skus') or [{}])[0].get('sku', ''),
                              'name': ((j2.get('order') or {}).get('skus') or [{}])[0].get('name', ''),
                              'result': '接口自测：扩增曲线正常，Ct 提前 1.2，无起线',
                              'attachments': ([{'name': att.get('name'), 'size': att.get('size'),
                                                'cloud_path': att.get('cloud_path')}] if att.get('cloud_path') else [])}]},
    'issue': '接口自测问题现象', 'quote': '接口自测客户原话', 'feedback': '接口自测客户反馈',
    'competitors': [{'brand': '诺唯赞', 'sku': 'X-Taq', 'perf': '灵敏度 5 copies/μL', 'feedback': '接口自测评价'}],
    'plan': [{'item': '寄送 2 支测试样品并附方案', 'owner': '刘新元', 'due': time.strftime('%Y-%m-%d')}],
}
st, j4 = req('/api/activity/submit', data=payload)
print('   HTTP', st, '｜ ok', j4.get('ok'), '｜ id', j4.get('id'), '｜ CloudBase', j4.get('cb'), (j4.get('cb_err') or '')[:120])
print('   —— 生成的飞书文本 ——')
print('\n'.join('   | ' + l for l in (j4.get('feishu_text') or '').split('\n')[:16]))

print('\n⑤ GET /api/activity/list + detail + attachment_url')
st, j5 = req('/api/activity/list')
print('   列表: HTTP', st, '｜ 条数', j5.get('total'))
st, j6 = req('/api/activity/detail?id=' + (j4.get('id') or ''))
print('   详情: HTTP', st, '｜ ok', j6.get('ok'), '｜ 客户', (j6.get('activity') or {}).get('customer', '')[:24],
      '｜ 附件', (j6.get('activity') or {}).get('att_count'))
if att.get('cloud_path'):
    st, j7 = req('/api/activity/attachment_url?path=' + urllib.parse.quote(att['cloud_path']))
    u = j7.get('url') or ''
    print('   附件地址: HTTP', st, '｜ ok', j7.get('ok'), '｜', (u[:88] + '…') if u else j7.get('error'))

print('\n  测试活动 id（待清理）:', j4.get('id'))
