import fs from 'node:fs';
import path from 'node:path';
import https from 'node:https';
import {spawn,execFileSync} from 'node:child_process';
import * as Effect from 'effect/Effect';
import * as Layer from 'effect/Layer';
import {RpcClient,RpcSerialization} from 'effect/rpc';
import {Socket} from 'effect/socket';
import * as NodeWS from '@effect/platform-node/NodeWS';
import {WsRpcGroup,ORCHESTRATION_PROTOCOL_VERSION} from '@t3tools/contracts';
const [checkout,side]=process.argv.slice(2);
const root=path.dirname(new URL(import.meta.url).pathname);
const out=path.join(root,`${side}-${Date.now()}`);fs.mkdirSync(out);
const started=Date.now(); const events=[];
function log(s){console.log(s);events.push([(Date.now()-started)/1000,s]);fs.writeFileSync(path.join(out,'events.json'),JSON.stringify(events));}
const host='github.localhost:19443'; let count=0;
const proxy=https.createServer({key:fs.readFileSync(path.join(root,'key.pem')),cert:fs.readFileSync(path.join(root,'cert.pem'))},(req,res)=>{count++;log(`PROXY request ${count}: ${req.method} ${req.url}`);res.writeHead(403,{'content-type':'text/html','retry-after':'5'});res.end('<html><body>Client certificate required</body></html>');});
await new Promise(r=>proxy.listen(19443,r));
const base=path.join(out,'state'); const workspace=path.join(out,'sample');fs.mkdirSync(workspace);fs.mkdirSync(path.join(base,'userdata'),{recursive:true});
function git(...args){return execFileSync('git',args,{cwd:workspace,stdio:'pipe'});}
git('init','-q');git('-c','user.name=Example','-c','user.email=example@example.invalid','commit','--allow-empty','-qm','Synthetic repository');git('remote','add','origin',`https://${host}/example/sample.git`);
const port=side==='before'?19441:19442;
const env={...process.env,T3CODE_DEV_SEED:'0',GH_HOST:host,GH_ENTERPRISE_TOKEN:'synthetic-local-credential',NODE_EXTRA_CA_CERTS:path.join(root,'cert.pem')};
// Never expose inherited credentials or provider configuration in the transcript.
for(const k of ['GH_TOKEN','GITHUB_TOKEN','GITHUB_ENTERPRISE_TOKEN','T3CODE_DEV_AUTH_TOKEN'])delete env[k];
const serverLog=fs.openSync(path.join(out,'server-private.log'),'w');
const cli=path.join(checkout,'apps/server/dist/bin.mjs');
const server=spawn('node',[cli,'serve','--host','127.0.0.1','--port',String(port),'--base-dir',base,'--no-browser','--log-level','warn',workspace],{cwd:checkout,env,stdio:['ignore',serverLog,serverLog]});
try{
 const origin=`http://127.0.0.1:${port}`;
 for(let i=0;i<120;i++){try{const ready=await fetch(`${origin}/.well-known/t3/environment`);if(ready.ok)break;}catch{}await new Promise(r=>setTimeout(r,500));}
 const token=execFileSync('node',[cli,'auth','session','issue','--base-dir',base,'--token-only'],{cwd:checkout,env,encoding:'utf8'}).trim().split('\n').at(-1);
 const headers={Authorization:`Bearer ${token}`,'content-type':'application/json','x-t3-orchestration-protocol':'2'};
 const projectId='11111111-1111-4111-8111-111111111111';
 const seed=await fetch(`${origin}/api/projects/mutate`,{method:'POST',headers,body:JSON.stringify({type:'project.create',commandId:crypto.randomUUID(),projectId,title:'Proxy refusal sample',workspaceRoot:workspace})});
 if(!seed.ok)throw new Error(`seed ${seed.status}: ${await seed.text()}`);
 const ticketRes=await fetch(`${origin}/api/auth/websocket-ticket`,{method:'POST',headers});const ticket=await ticketRes.json();
 if(!ticketRes.ok)throw new Error(`ticket ${ticketRes.status} ${JSON.stringify(ticket)}`);
 log(`T3 Code real server | ${side.toUpperCase()} | commit ${execFileSync('git',['rev-parse','HEAD'],{cwd:checkout,encoding:'utf8'}).trim()}`);
 log('Environment: Linux; built Node server; isolated fresh database; synthetic GitHub Enterprise repository.');
 log('Proxy: HTTPS; HTTP 403; Content-Type: text/html; Retry-After: 5; no X-RateLimit headers.');
 await Effect.runPromise(Effect.scoped(Effect.gen(function*(){
  const protocol=yield* Layer.build(RpcClient.layerProtocolSocket().pipe(Layer.provide(Socket.layerWebSocket(`${origin.replace('http','ws')}/ws?orchestrationProtocol=${ORCHESTRATION_PROTOCOL_VERSION}&wsTicket=${encodeURIComponent(ticket.ticket)}`)),Layer.provide(RpcSerialization.layerJson),Layer.provide(NodeWS.layerWebSocketConstructor)));
  const client=yield* RpcClient.make(WsRpcGroup).pipe(Effect.provideContext(protocol));
  for(const number of [1,2]){
   yield* Effect.promise(()=>new Promise(r=>setTimeout(r,1000)));
   log(`STEP ${number}: read checks for synthetic PR ${number} (same host, separate cache key).`);
   const result=yield* Effect.result(client['pullRequests.checks']({projectId,host,repository:'example/sample',number}));
   if(result._tag==='Failure')log(`SERVER ERROR: ${result.failure.message ?? result.failure.detail ?? JSON.stringify(result.failure)}`);else log(`SERVER RESULT: ${JSON.stringify(result.success)}`);
   log(`Proxy requests received so far: ${count}`);
  }
 })));
 log(`FINISHED: ${count} outbound proxy request(s).`);
 fs.writeFileSync(path.join(out,'transcript.txt'),events.map(([t,s])=>`[${t.toFixed(3)}s] ${s}`).join('\n')+'\n');

}finally{server.kill('SIGTERM');proxy.close();}
