import os, sys, pathlib, subprocess, time, json, urllib.request, urllib.error, signal, datetime, re, http.cookiejar
side, checkout, port = sys.argv[1], pathlib.Path(sys.argv[2]).resolve(), int(sys.argv[3])
root = pathlib.Path(__file__).parent
out = root / (side + '-' + datetime.datetime.now(datetime.timezone.utc).strftime('%Y%m%dT%H%M%SZ'))
out.mkdir()
home = out / 'home'
runtime = home / 'runtime' / 'versions' / '0.1.8'
runtime.mkdir(parents=True)
entry = runtime / 't3'
entry.write_text('#!/bin/sh\nexec ' + json.dumps(subprocess.check_output(['which','node'],text=True).strip()) + ' ' + json.dumps(str(checkout/'apps/server/dist/bin.mjs')) + ' "$@"\n')
entry.chmod(0o755)
(runtime/'.install-complete').write_text('0.1.8\n')
state = home/'runtime/service-state.json'
state.write_text('{"protocol":2,"activeVersion":"0.1.8"}\n')
env = os.environ.copy()
for key in list(env):
    if key.startswith(('T3','VITE_')): env.pop(key)
env.update(T3CODE_HOME=str(home), T3CODE_DEV_SEED='0', T3CODE_PORT=str(port),T3CODE_HOST='127.0.0.1',T3CODE_NO_BROWSER='true',T3CODE_TELEMETRY_CHANNEL='dev')
start=time.monotonic()
events=[]
def event(msg):
    elapsed=round(time.monotonic()-start,2)
    events.append({'seconds':elapsed,'text':msg})
    print(f'[{elapsed:05.2f}s] {msg}',flush=True)
event('Linux x86_64 | isolated fresh T3 home | built CLI + real server')
event('Commit: '+subprocess.check_output(['git','rev-parse','HEAD'],cwd=checkout,text=True).strip())
event('Seed service-state.json: '+state.read_text().strip())
event('Installed runtime: real bundled CLI, version 0.1.8; install-complete sentinel present')
event('Run: t3 __service-launcher')
raw=open(out/'private-server.log','w')
p=subprocess.Popen(['node',str(checkout/'apps/server/dist/bin.mjs'),'__service-launcher'],env=env,cwd=checkout,stdout=raw,stderr=raw,start_new_session=True)
ready=False
try:
    for n in range(240):
        if p.poll() is not None:
            event('Launcher exited: '+str(p.returncode)); break
        if 'T3 Code server is ready.' in (out/'private-server.log').read_text():
            ready=True; event('Real server output: T3 Code server is ready.'); break
        time.sleep(.25)
    if ready:
        token=re.search(r'^Token: (.+)$',(out/'private-server.log').read_text(),re.M).group(1)
        client=urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
        request=urllib.request.Request(f'http://127.0.0.1:{port}/api/auth/browser-session',data=json.dumps({'credential':token}).encode(),headers={'Content-Type':'application/json'})
        with client.open(request,timeout=5) as response:
            event('Client pairing: POST /api/auth/browser-session -> HTTP '+str(response.status))
        with client.open(f'http://127.0.0.1:{port}/api/auth/session',timeout=5) as response:
            event('Authenticated client: GET /api/auth/session -> HTTP '+str(response.status))
    raw.flush()
    text=(out/'private-server.log').read_text()
    for line in text.splitlines():
        if '[service-launcher]' in line: event(line)
    if not ready:
        try:
            urllib.request.urlopen(f'http://127.0.0.1:{port}/api/auth/session',timeout=2)
            event('HTTP: unexpected response')
        except urllib.error.URLError as e:
            event('HTTP: connection refused; server never started' if isinstance(e.reason,ConnectionRefusedError) else 'HTTP request failed: '+str(e.reason))
    event('On-disk state after startup: '+state.read_text().strip())
    event('Observed: '+('server ready; client paired and authenticated after legacy install adoption' if ready else 'launcher rejects legacy install before spawning server'))
    if ready: time.sleep(2)
finally:
    if p.poll() is None:
        p.send_signal(signal.SIGTERM)
        try:p.wait(timeout=15)
        except subprocess.TimeoutExpired:os.killpg(p.pid,signal.SIGKILL);p.wait()
    raw.close()
event('Captured launcher and its child stopped')
(out/'events.json').write_text(json.dumps(events,indent=2))
(out/'transcript.txt').write_text('\n'.join(f'[{e["seconds"]:05.2f}s] {e["text"]}' for e in events)+'\n')
print('OUTPUT '+str(out))
