"""Verify pushed Guoxin commit and native relations before QA handoff; no MR/deployment."""
import datetime
import html
import json
import subprocess
import sys
from pathlib import Path

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

OWNER='635755195dc8531eeb2e33d9'
items=json.loads((HERE/'items.sanitized.json').read_text())
STATE=HERE/'delivery.sanitized.json'
state=json.loads(STATE.read_text()) if STATE.exists() else {'items':{}}
def save(): STATE.write_text(json.dumps(state,ensure_ascii=False,indent=2)+'\n')
def rows(v): return v if isinstance(v,list) else (v or {}).get('result',(v or {}).get('items',[]))
def git(*args): return subprocess.check_output(['git','-C',str(REPO),*args],text=True).strip()
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 relations(item_id):
    for pre in [PREFIX+'/workitems/','/oapi/v1/projex/workitems/']:
        try: return pre,rows(api('GET',pre+item_id+'/extRelationRecords?category=codeupCommit'))
        except RuntimeError as e:
            if 'HTTP 404' not in str(e): raise
    raise RuntimeError('Native commit relation API unavailable')

assert git('branch','--show-current')=='guoxin_develop'
assert git('status','--porcelain')=='', 'Business worktree must be clean after scoped commit'
sha=git('rev-parse','HEAD');subject=git('show','-s','--format=%s',sha)
assert subject.startswith('#'+items['tasks']['development']['serialNumber']+' ')
remote=git('ls-remote','--heads','origin','refs/heads/guoxin_develop').split()[0]
assert sha==remote
repo=api('GET',f'/oapi/v1/codeup/organizations/{ORG}/repositories/4913137')
assert repo['pathWithNamespace']==ORG+'/zhct/store'
commit=api('GET',f'/oapi/v1/codeup/organizations/{ORG}/repositories/4913137/commits/{sha}')
assert commit.get('id',commit.get('sha'))==sha
url=repo['webUrl']+'/commit/'+sha
state.update({'commit':sha,'subject':subject,'branch':'guoxin_develop','remoteHead':remote,
    'repositoryId':4913137,'commitUrl':url,'mrCreated':False,
    'mrReason':'用户明确同分支提交和原生代码关联，不向通用release创建跨客户MR；未部署。'})
save()

for key,item,target,document in [
    ('parent',items['parent'],'1dec9023be7be6cf79e6bde901','parent-use-case.md'),
    ('development',items['tasks']['development'],'100011','development-task.md'),
    ('validation',items['tasks']['validation'],'100010','validation-task.md'),
]:
    current=api('GET',PREFIX+'/workitems/'+item['id'])
    assert current['assignedTo']['id']==OWNER
    wf=api('GET',PREFIX+'/workitems/'+item['id']+'/workflow')
    assert any(s['id']==target for s in wf['statuses'])
    assert current['status']['id'] in ['100005','100010','142838',target], 'Refuse to rewind advanced work item'
    pre,existing=relations(item['id'])
    if not any(r.get('businessId',r.get('commitSha'))==sha and str(r.get('projectId'))=='4913137' for r in existing):
        api('POST',pre+item['id']+'/extRelationRecords',{'category':'codeupCommit','projectId':'4913137','commitSha':sha,'title':subject,'url':url})
    _,linked=relations(item['id'])
    assert any(r.get('businessId',r.get('commitSha'))==sha and str(r.get('projectId'))=='4913137' for r in linked)
    text=(HERE/document).read_text()+('\n## 已交付代码与状态\n- '+subject+'\n- '+sha+'\n- '+url+
        '\n- 父需求'+items['parent']['serialNumber']+'；开发'+items['tasks']['development']['serialNumber']+'；测试'+items['tasks']['validation']['serialNumber']+'。'
        '\n- guoxin_develop本地远端SHA一致，11个源码/菜单/测试文件，不含prompt/docs/凭据/私密数据/构建产物。'
        '\n- PHP专项15例63断言、国信161例2023断言、前端17套76例、Node14构建通过；真实开发HTTP队列/OSS/XLSX/本人日志/下载通过，资金流水校验未变。'
        '\n- 最终界面仅日期/当前部门/收支/关键词；已删除三个筛选与两行说明，列表和导出列保留。'
        '\n- 横向拖拽和窄屏/部署加载/生产规模压测未验；全量26既有失败、原lint配置阻断未冒通过。'
        '\n- 父需求待测试，开发任务开发完成，测试任务处理中；这不是已上线或测试全部完成。'
        '\n- 用户明确不建跨客户release MR，未合并master_guoxin、未部署、未重启客户worker。'
        '\n- 预计非AI开发8h/测试4h；实际只登记有精确时间戳的本轮补录及交付窗口，前期未完整计时不估填。\n')
    api('PUT',PREFIX+'/workitems/'+item['id'],{'description':rich(text),'formatType':'RICHTEXT','status':target})
    result=api('GET',PREFIX+'/workitems/'+item['id'])
    assert result['status']['id']==target and result['assignedTo']['id']==OWNER
    for marker in ['Use Case','UC-GX-WALLET-FLOW-001','主流程','异常/恢复','验收标准','测试矩阵','DoR',sha]: assert marker in result['description'],marker
    marker='GX-WALLET-DELIVERY-'+sha[:9]
    comments=PREFIX+'/workitems/'+item['id']+'/comments'
    if not any(marker in str(c.get('content','')) for c in rows(api('GET',comments))):
        api('POST',comments,{'content':marker+'\n'+subject+'\n'+url+'\n真实commit已原生关联并GET回读，不只是评论。UC-GX-WALLET-FLOW-001 v1.1，四项筛选和逐笔合计；PHP15/63、国信161/2023、Jest17/76、Node14及真实异步导出通过。横拖/窄屏/部署压力待验，QA任务处理中；全量既有26失败不冒全绿。仅按用户要求同分支交付，无跨客户MR或生产部署。预计8h+4h，实际仅可核验窗口。'})
    assert any(marker in str(c.get('content','')) for c in rows(api('GET',comments)))
    state['items'][key]={**compact(result),'commitRelationConfirmed':True,'commentReadbackConfirmed':True};save()
    print(result['serialNumber'],result['status']['name'],'native commit relation confirmed',flush=True)

# Exact observed window starts at the recorded local date receipt, not an inferred all-day effort.
task=items['tasks']['development']
path=PREFIX+'/workitems/'+task['id']+'/effortRecords'
marker='GX-WALLET-OBSERVED-DELIVERY-20261019'
matches=[r for r in rows(api('GET',path)) if marker in str(r.get('description',''))]
assert len(matches)<=1
if not matches:
    start=datetime.datetime.fromisoformat('2026-10-19T18:05:51+08:00')
    end=datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8)))
    actual=round((end-start).total_seconds()/3600,2)
    assert 0<actual<4, 'Unexpected delivery window; inspect before recording'
    api('POST',path,{'operatorId':OWNER,'actualTime':actual,'gmtStart':int(start.timestamp()*1000),'gmtEnd':int(end.timestamp()*1000),
        'description':marker+' 仅本轮已核验的UC补录/计划拆解、提交复核、远程推送和云效关联窗口，小时保留两位；此前方案开发验收未完整计时，未估填，不累计并行代理。QA实际暂不填虚构值。'})
records=rows(api('GET',path));matches=[r for r in records if marker in str(r.get('description',''))]
assert len(matches)==1 and matches[0]['owner']['id']==OWNER
state['actualEffort']={k:matches[0].get(k) for k in ['id','actualTime','gmtStart','gmtEnd','description']}
for key in ['development','validation']:
    task=items['tasks'][key];full=api('GET',PREFIX+'/workitems/'+task['id'])
    fields={str(f['fieldId']):f['values'][0]['identifier'] for f in full.get('customFieldValues',[]) if f.get('values')}
    assert fields['79'].startswith(task['planStart']) and fields['80'].startswith(task['planEnd'])
    assert float(fields['101586'])==task['estimatedHours']
    state['items'][key]['planStart']=task['planStart'];state['items'][key]['planEnd']=task['planEnd']
    state['items'][key]['estimatedHours']=task['estimatedHours']
    state['items'][key]['actualHoursReadback']=float(fields.get('101587',0))
    if key=='development': assert float(fields['101587'])>=float(matches[0]['actualTime'])
state['allReadbacksConfirmed']=True;save()
print(json.dumps({'commit':sha,'items':state['items'],'observedActualHours':state['actualEffort']['actualTime']},ensure_ascii=False,indent=2))
