from pathlib import Path
import sys,subprocess,time,urllib.request,urllib.error,hashlib,re,socket
import collector as c
c.ENV['FORUM_REPOSITORY_ROOT']=str(c.ROOT/'history-fixtures-final/ordinary');c.ENV['FORUM_DATABASE_PATH']=str(c.ROOT/'history.sqlite');c.ENV['FORUM_STATIC_HTML_ROOT']=str(c.ROOT/'history-static')
n=int(sys.argv[1]);sock=socket.socket();sock.bind(('127.0.0.1',0));port=sock.getsockname()[1];sock.close()
serverlog=open(c.ROOT/f'http-{n}-server.log','wb')
p=subprocess.Popen(['php','-S',f'127.0.0.1:{port}','-t',str(c.APP/'public'),str(c.ROOT/'router.php')],cwd=c.APP,env=c.ENV,stdout=serverlog,stderr=serverlog)
try:
 for _ in range(100):
  try:
   s=socket.create_connection(('127.0.0.1',port),.1);s.close();break
  except OSError:time.sleep(.05)
 routes=['/','/latest','/top','/search?search=qqqq','/400000','/api/get_post?post_id=thread-20261030000000-qdb-400000','/activity']
 if n==-1:routes=['/activity','/threads/root-001','/api/get_post?post_id=root-001']
 if n==1:routes=['/400000','/api/get_post?post_id=thread-20261030000000-qdb-400000']
 for route in routes:
  previous=None
  for repeat in range(3):
   started=time.monotonic()
   try:
    with urllib.request.urlopen(f'http://127.0.0.1:{port}'+route,timeout=30) as response:body=response.read();status=response.status
   except urllib.error.HTTPError as e:body=e.read();status=e.code
   elapsed=time.monotonic()-started
   ids=list(dict.fromkeys(re.findall(rb'thread-20261030000000-qdb-\d+',body)))
   key=hashlib.sha256(b'\n'.join(ids)).hexdigest()
   stable=previous is None or previous==key;previous=key
   print(f'Sample: read-{n}-{route}-{repeat}\nStatus: {status}\nElapsed seconds: {elapsed:.6f}\nResponse bytes: {len(body)}\nDistinct synthetic IDs: {len(ids)}\nOrdered ID hash: {key}\nIDs stable: {stable}\nBody SHA256: {hashlib.sha256(body).hexdigest()}\n',flush=True)
   (c.ROOT/f'response-{n}-{routes.index(route)}-{repeat}.txt').write_bytes(body)
   if status!=200 or not stable or (route in ('/latest','/top','/search?search=qqqq') and len(ids)!=25):raise RuntimeError('semantic/status mismatch; halt this route campaign')
finally:
 p.terminate();p.wait(timeout=5);serverlog.close()