# -*- coding: utf-8 -*-
"""Record audited root elapsed work once; do not add parallel agents or idle waits."""
import json
from pathlib import Path
from datetime import datetime,timezone
from transport import api,PREFIX
HERE=Path(__file__).resolve().parent
ROOT=HERE.parents[2]
RUNTIME=HERE.parent/'runtime/yunxiao'
state=json.loads((HERE/'items.sanitized.json').read_text())
timeline=json.loads((RUNTIME/'effort-timeline.private.json').read_text())
owner='635755195dc8531eeb2e33d9'
planfile=HERE/'actual-effort-plan.sanitized.json'
def parse(x):return datetime.fromisoformat(x.replace('Z','+00:00'))
def ms(x):return int(parse(x).timestamp()*1000)
if planfile.exists(): plan=json.loads(planfile.read_text())
else:
    plan=[]
    for key,phase,label in [('analysis','analysis','需求理解/代码数据库核验/方案'),('development','implementation','实现/联调/第一轮自测'),('validation','validation','开发库测试/回归/审查/验收')]:
        rows=timeline['turns'][phase];start=min(x['start'] for x in rows);end=max(x['end'] for x in rows)
        seconds=sum(x['seconds'] for x in rows)
        plan.append({'key':key,'marker':'20261015-RECEIPT-'+phase,'label':label,'actualTime':round(seconds/3600,2),'seconds':round(seconds,3),'gmtStart':ms(start),'gmtEnd':ms(end)})
    active=timeline['turns']['active'];assert len(active)==1
    start=active[0]['start'];end=datetime.now(timezone.utc);seconds=(end-parse(start)).total_seconds()
    plan.append({'key':'development','marker':'20261015-RECEIPT-submission','label':'云效UC/任务/原型发布/代码提交关联收尾（截至登记时）','actualTime':round(seconds/3600,2),'seconds':round(seconds,3),'gmtStart':ms(start),'gmtEnd':int(end.timestamp()*1000)})
    planfile.write_text(json.dumps(plan,ensure_ascii=False,indent=2))
result={}
for p in plan:
    p['actualTime']=round(p['seconds']/3600,1)
    tid=state['tasks'][p['key']]['id'];path=PREFIX+'/workitems/'+tid+'/effortRecords'
    rows=api('GET',path) or []
    if not isinstance(rows,list):rows=rows.get('result',rows.get('items',[]))
    matches=[x for x in rows if p['marker'] in (x.get('description') or '')]
    assert len(matches)<=1,'Duplicate effort markers'
    if not matches or matches[0].get('owner',{}).get('id')!=owner or abs(float(matches[0]['actualTime'])-p['actualTime'])>0.001:
        body={'operatorId':owner,'actualTime':p['actualTime'],'gmtStart':p['gmtStart'],'gmtEnd':p['gmtEnd'],
              'description':p['marker']+' '+p['label']+'；依据本线程root task_started到完成/中止的有效执行时段，排除用户等待，不叠加并行子代理。云效按0.1小时登记，原始秒数保留审计；不是无AI预计工时，也不是人工纯编码时长。'}
        api('PUT' if matches else 'POST',path+('/'+matches[0]['id'] if matches else ''),body)
    readback=api('GET',path) or []
    if not isinstance(readback,list):readback=readback.get('result',readback.get('items',[]))
    matches=[x for x in readback if p['marker'] in (x.get('description') or '')]
    assert len(matches)==1,'Effort readback missing or duplicate'
    row=matches[0]
    assert row.get('owner',{}).get('id')==owner,'Actual effort owner mismatch'
    assert abs(float(row['actualTime'])-p['actualTime'])<0.001
    result[p['marker']]={k:row.get(k) for k in ['id','actualTime','gmtStart','gmtEnd','description','owner']}
    result[p['marker']]['task']=state['tasks'][p['key']]['serialNumber']
planfile.write_text(json.dumps(plan,ensure_ascii=False,indent=2))
(HERE/'actual-effort-readback.sanitized.json').write_text(json.dumps(result,ensure_ascii=False,indent=2))
print(json.dumps({'records':result,'total_actual':round(sum(x['actualTime'] for x in plan),2),'total_estimated':16},ensure_ascii=False))
