#!/usr/bin/env python3
import base64,datetime,json,os,pathlib,secrets,subprocess,urllib.request,urllib.error,time
S=pathlib.Path(os.environ.get('CAPTURE_ROOT','/tmp/lead-32738-r1/capture-2')); R=S/('fixture-'+datetime.datetime.now(datetime.timezone.utc).strftime('%Y%m%dT%H%M%SZ')); R.mkdir()
api='http://localhost:33038'; remote='http://forgejo.127.0.0.1.nip.io:33038'; owner='evidence'
password=json.loads((S/'secrets.json').read_text())['password'] if (S/'secrets.json').exists() else secrets.token_urlsafe(24)
if not (S/'secrets.json').exists(): subprocess.run(['docker','exec','--user','git','capture2-32738-forgejo','forgejo','admin','user','create','--username',owner,'--password',password,'--email','evidence@example.test','--admin','--must-change-password=false'],check=True,stdout=subprocess.DEVNULL)
auth='Basic '+base64.b64encode((owner+':'+password).encode()).decode()
def req(path,method='GET',body=None):
 h={'Authorization':auth,'Content-Type':'application/json'}
 with urllib.request.urlopen(urllib.request.Request(api+'/api/v1/'+path,data=json.dumps(body).encode() if body is not None else None,headers=h,method=method)) as r:return json.load(r) if r.status!=204 else None
token=json.loads((S/'secrets.json').read_text())['token'] if (S/'secrets.json').exists() else req('users/evidence/tokens','POST',{'name':'capture-32738','scopes':['all']})['sha1']
(S/'secrets.json').write_text(json.dumps({'token':token,'password':password})); (S/'secrets.json').chmod(0o600)
auth='token '+token
env={**os.environ,'XDG_CONFIG_HOME':str(S/'config'),'GITEA_SERVER_TOKEN':token,'NO_PROXY':os.environ.get('NO_PROXY','')+',forgejo.127.0.0.1.nip.io'}
if not (S/'config/tea/config.yml').exists(): subprocess.run([str(S/'bin/tea'),'login','add','--name','capture-forgejo','--url',remote],env=env,check=True,stdout=subprocess.DEVNULL)
def git(cwd,*args):
 return subprocess.check_output(['git','-C',str(cwd),*args],env={**env,'GIT_AUTHOR_DATE':'2026-01-15T12:00:00Z','GIT_COMMITTER_DATE':'2026-01-15T12:00:00Z'},stderr=subprocess.DEVNULL,text=True).strip()
fixtures=[]
for repo in ['ff','mix','diverged']:
 try: req(f'repos/{owner}/{repo}')
 except urllib.error.HTTPError: req('user/repos','POST',{'name':repo,'private':False,'auto_init':False,'default_branch':'main'})
 req(f'repos/{owner}/{repo}','PATCH',{'has_pull_requests':True,'allow_merge_commits':False,'allow_squash_merge':False,'allow_rebase':repo=='mix','allow_rebase_explicit':False,'allow_fast_forward_only_merge':True,'default_merge_style':'fast-forward-only','default_delete_branch_after_merge':False})
 d=R/repo;d.mkdir();git(d,'init','-b','main');git(d,'config','user.name','Evidence');git(d,'config','user.email','evidence@example.test');git(d,'config','credential.helper',f'!{S}/bin/tea login helper');git(d,'remote','add','origin',f'{remote}/{owner}/{repo}.git')
 (d/'README.md').write_text('# Fast-forward evidence\n');git(d,'add','.');git(d,'commit','-m','Initial fixture');git(d,'push','-u','origin','main')
 branches=['idle','success','compact'] if repo=='ff' else ['feature']
 for branch in branches:
  git(d,'checkout','main');git(d,'checkout','-b',branch);(d/(branch+'.txt')).write_text('Synthetic fast-forward fixture.\n');git(d,'add','.');git(d,'commit','-m','Add '+branch);git(d,'push','-u','origin',branch)
  for attempt in range(10):
   try:
    p=req(f'repos/{owner}/{repo}/pulls','POST',{'base':'main','head':branch,'title':'Fast-forward '+branch,'body':'Synthetic merge evidence.'});break
   except urllib.error.HTTPError as e:
    if attempt==9: raise
    time.sleep(1)
  print('Created',repo,branch,p['number'],flush=True)
  fixtures.append({'repo':repo,'branch':branch,'number':p['number'],'url':p['html_url'],'clone':str(d),'head':git(d,'rev-parse','HEAD')})
 if repo=='diverged':
  git(d,'checkout','main');(d/'base-only.txt').write_text('Advance main independently.\n');git(d,'add','.');git(d,'commit','-m','Advance base');git(d,'push')
 git(d,'checkout',branches[0])
(S/'fixtures.json').write_text(json.dumps(fixtures,indent=2));print(json.dumps(fixtures,indent=2))

# Pin fixture issue times to the display clock, including on a clean rebuild.
subprocess.run(["docker","exec","capture2-32738-forgejo","sqlite3","/data/gitea/gitea.db","UPDATE issue SET created_unix=1794313380, updated_unix=1794313380;"],check=True)
