"""Task-scoped idempotent Yunxiao setup. Personal token stays in ignored config."""
import datetime
import html
import json
import sys
from pathlib import Path

HERE = Path(__file__).resolve().parent
ROOT = HERE.parents[1]
sys.path.insert(0, str(ROOT / 'work_store/VWCG-1450-consume-order-department-bulk-select/yunxiao'))
from transport import api, PREFIX, SPACE, compact

OWNER = '635755195dc8531eeb2e33d9'
TITLE = '国信账户管理：补贴钱包逐笔流水查询与异步导出'
STATE = HERE / 'items.sanitized.json'
state = json.loads(STATE.read_text()) if STATE.exists() else {'tasks': {}}

def rows(value):
    return value if isinstance(value, list) else (value or {}).get('result', (value or {}).get('items', []))

def save():
    STATE.write_text(json.dumps(state, ensure_ascii=False, indent=2) + '\n')

def rich(text):
    return ''.join('<h2>'+html.escape(s[3:])+'</h2>' if s.startswith('## ') else '<p>'+html.escape(s)+'</p>' for s in text.splitlines() if s)

def find(category, subject, parent=None):
    found=[]
    for page in range(1,31):
        batch=rows(api('POST',PREFIX+'/workitems:search',{'spaceId':SPACE,'category':category,'page':page,'perPage':200,'orderBy':'gmtCreate','sort':'desc'}))
        found.extend(i for i in batch if i.get('subject')==subject and (parent is None or i.get('parentId')==parent))
        if len(batch)<200: break
    else: raise RuntimeError('Search pagination incomplete')
    if len(found)>1: raise RuntimeError('Duplicate work items; refusing another create')
    return found[0]['id'] if found else None

def check(item):
    assert item['space']['id']==SPACE and item['assignedTo']['id']==OWNER
    for marker in ['Use Case','UC-GX-WALLET-FLOW-001','主流程','异常/恢复','验收标准','测试矩阵','DoR','READY']:
        assert marker in item.get('description',''), marker

parent_id=state.get('parent',{}).get('id') or find('Req',TITLE)
if not parent_id:
    result=api('POST',PREFIX+'/workitems',{
        'spaceId':SPACE,'workitemTypeId':'9uy29901re573f561d69jn40','subject':TITLE,
        'description':(HERE/'parent-use-case.md').read_text(),'documentFormat':'MARKDOWN',
        'assignedTo':OWNER,'participants':[OWNER],'status':'100005',
    })
    parent_id=str(result.get('id',result.get('identifier')) if isinstance(result,dict) else result)
    assert parent_id and parent_id!='None'
    state['parent']={'id':parent_id};save()
parent=api('GET',PREFIX+'/workitems/'+parent_id)
assert parent['subject']==TITLE and parent['assignedTo']['id']==OWNER
api('PUT',PREFIX+'/workitems/'+parent_id,{'description':rich((HERE/'parent-use-case.md').read_text()),'formatType':'RICHTEXT'})
parent=api('GET',PREFIX+'/workitems/'+parent_id);check(parent)
state['parent']=compact(parent);save()
print(parent['serialNumber'],parent['subject'],flush=True)

for key,title,doc,estimate,finish in [
    ('development','开发与自测：国信补贴钱包逐笔流水查询及异步导出','development-task.md',8,'2026-10-19'),
    ('validation','测试与验收：国信补贴流水金额、权限、异步导出及页面回归','validation-task.md',4,'2026-10-20'),
]:
    item_id=state['tasks'].get(key,{}).get('id') or find('Task',title,parent_id)
    text=(HERE/doc).read_text()+'\n关联父需求：'+parent['serialNumber']+'\n'
    if not item_id:
        result=api('POST',PREFIX+'/workitems',{
            'spaceId':SPACE,'workitemTypeId':'ba102e46bc6a8483d9b7f25c','subject':title,
            'description':text,'documentFormat':'MARKDOWN','assignedTo':OWNER,'participants':[OWNER],
            'parentId':parent_id,'status':'100005','customFieldValues':{'79':'2026-10-19','80':finish},
        })
        item_id=str(result.get('id',result.get('identifier')) if isinstance(result,dict) else result)
        assert item_id and item_id!='None'
        state['tasks'][key]={'id':item_id};save()
    current=api('GET',PREFIX+'/workitems/'+item_id)
    assert current['parentId']==parent_id and current['assignedTo']['id']==OWNER
    api('PUT',PREFIX+'/workitems/'+item_id,{'description':rich(text),'formatType':'RICHTEXT'})
    workflow=api('GET',PREFIX+'/workitems/'+item_id+'/workflow')
    assert any(s['id']=='100010' for s in workflow['statuses'])
    if current['status']['id']=='100005': api('PUT',PREFIX+'/workitems/'+item_id,{'status':'100010'})
    if not rows(api('GET',PREFIX+'/workitems/'+item_id+'/estimatedEfforts')):
        api('POST',PREFIX+'/workitems/'+item_id+'/estimatedEfforts',{'spentTime':estimate,'owner':OWNER,
            'description':'非AI完整分析设计、实现自测审查或验收预计投入；不是实际工时，不是客户上线承诺。'})
    current=api('GET',PREFIX+'/workitems/'+item_id);check(current)
    fields={str(f['fieldId']):f['values'][0]['identifier'] for f in current.get('customFieldValues',[]) if f.get('values')}
    assert fields['79'].startswith('2026-10-19') and fields['80'].startswith(finish)
    assert float(fields['101586'])==estimate
    state['tasks'][key]={**compact(current),'planStart':'2026-10-19','planEnd':finish,'estimatedHours':estimate};save()
    print(current['serialNumber'],current['subject'],'estimate',estimate,flush=True)
state['createdAndReadbackAt']=datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8))).isoformat();save()
print(json.dumps({'parent':state['parent'],'tasks':state['tasks']},ensure_ascii=False,indent=2))
