#!/usr/bin/env python3
"""批量刷新顺丰路由 - 逐条查询版（修复SF批量API限制）"""
import json, os, sys, time, urllib.request, urllib.parse, uuid

PI='BRSWK5CQ08HV'; SK='V7JDT0azGX93pnIXRyZe9zvlzY6fk1rC'
DATA=os.path.expanduser('~/Desktop/Hermes输出-工作类/数据')
SHIP=os.path.join(DATA,'shipment_status.json')

def phone4(o):
    digits=''.join(c for c in str(o.get('phone') or '') if c.isdigit())
    return digits[-4:] if len(digits)>=4 else None

def sf_token():
    body=urllib.parse.urlencode({'partnerID':PI,'secret':SK,'grantType':'password'}).encode()
    req=urllib.request.Request('https://sfapi.sf-express.com/oauth2/accessToken',data=body,headers={'Content-Type':'application/x-www-form-urlencoded'})
    return json.loads(urllib.request.urlopen(req,timeout=30).read())['accessToken']

def sf_query_one(tn,check_phone,token):
    msg={'language':'zh-CN','trackingType':1,'trackingNumber':[tn],'methodType':1,'checkPhoneNo':check_phone}
    body=urllib.parse.urlencode({'partnerID':PI,'requestID':str(uuid.uuid4()).replace('-',''),'serviceCode':'EXP_RECE_SEARCH_ROUTES','timestamp':str(int(time.time())),'accessToken':token,'msgData':json.dumps(msg,ensure_ascii=False)}).encode()
    req=urllib.request.Request('https://bspgw.sf-express.com/std/service',data=body,headers={'Content-Type':'application/x-www-form-urlencoded;charset=utf-8'})
    r=json.loads(urllib.request.urlopen(req,timeout=30).read())
    d=json.loads(r.get('apiResultData','{}'))
    rr=d.get('msgData',{}).get('routeResps',[])
    return rr[0] if rr else {}

with open(SHIP) as f: ship=json.load(f)
orders=ship['orders']

pending=[]
for o in orders:
    tn=(o.get('trackingNo') or '').strip()
    if not tn: continue
    s=o.get('shipment') or {}
    if s.get('status')=='delivered': continue
    if s.get('routes'): continue
    p4=phone4(o)
    if not p4: continue
    pending.append((o,tn,p4))

print(f'待查询: {len(pending)}条')
token=sf_token()
n_ok=0

for idx,(o,tn,p4) in enumerate(pending):
    try:
        resp=sf_query_one(tn,p4,token)
        routes=resp.get('routes',[])
        if not routes: continue
        n_ok+=1
        last=routes[-1]
        o['shipment']={
            'mailNo':tn,'routes':routes,'routeCount':len(routes),
            'status':'in_transit','statusLabel':'运输中',
            'lastRoute':{'acceptAddress':last.get('acceptAddress',''),'acceptTime':last.get('acceptTime',''),'secondaryStatusName':last.get('secondaryStatusName',''),'remark':(last.get('remark','') or '')[:200]}
        }
    except Exception as e:
        if idx<5: print(f'  ❌ {tn}: {e}',file=sys.stderr)
    if idx%50==0: print(f'  [{idx}/{len(pending)}] {n_ok}OK',file=sys.stderr)
    time.sleep(0.15)

ship['updated_at']=time.strftime('%Y-%m-%d %H:%M:%S')
with open(SHIP,'w') as f: json.dump(ship,f,ensure_ascii=False)
print(f'✅ 完成: {n_ok}新增路由 | {len(pending)-n_ok}仍失败')
