import { expect } from "e2e";
import fs from "node:fs";
import crypto from "node:crypto";
import * as NodeWS from "@effect/platform-node/NodeWS";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import { RpcClient, RpcSerialization } from "effect/rpc";
import { Socket } from "effect/socket";
import { WsRpcGroup, ORCHESTRATION_PROTOCOL_VERSION } from "@t3tools/contracts";
import { test, WEB, makeState, runPromise } from "./t3.ts";
import { T3_HOME } from "../e2e.config.ts";

test("An Auto parent recovers its existing Full-access child on another account", WEB, async ({t3,app,screen,browser})=>{
 await browser.setViewport({width:1440,height:1000});
 const project=await t3.project("Account recovery");
 const {cli}=makeState(T3_HOME);
 const started=await runPromise(cli(["thread","start",project,"Start recovery demonstration","--title","Recovery parent","--provider","accountA","--model","showcase","--wait","--json"]));
 const {threadId}=JSON.parse(started.stdout);
 const unrelated=await runPromise(cli(["thread","start",project,"Unrelated Full-access target","--title","Unrelated target","--provider","accountA","--model","showcase","--wait","--json"]));
 fs.writeFileSync(project+"/.unrelated-proof.json",unrelated.stdout);
 const auth=await runPromise(cli(["auth","session","issue","--token-only"]));
 const {origin}=JSON.parse(fs.readFileSync(T3_HOME+"/userdata/server-runtime.json","utf8"));
 const token=auth.stdout.trim().split('\n').at(-1)!;
 const ticket=await (await fetch(origin+"/api/auth/websocket-ticket",{method:"POST",headers:{Authorization:"Bearer "+token}})).json();
 const setMode=async(runtimeMode:string)=>await runPromise(Effect.gen(function*(){
  const protocol=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 context=yield* Layer.build(protocol);
  const client=yield* RpcClient.make(WsRpcGroup).pipe(Effect.provideContext(context));
  yield* client["orchestration.dispatchCommand"]({type:"thread.runtime-mode.set",commandId:crypto.randomUUID(),threadId,runtimeMode} as never);
 }).pipe(Effect.scoped));
 await t3.open();
 await screen.getByRole("button","Recovery parent, Done, Account recovery",{exact:true}).tap();
 const send=async(text:string)=>{await screen.getByRole("textbox").fill(text);await screen.getByRole("textbox").press("Enter");};
 await send("PROOF_DELEGATE: delegate a Full-access child to remember a code word.");
 await screen.getByText("Delegation complete.",{exact:false}).waitFor({state:"visible"});
 // Local ACP drivers hide the permission picker; use the same client RPC command.
 await setMode("auto");
 await send("PROOF_RECOVER: switch the same child to Account B and continue its conversation.");
 await screen.getByText("Recovery finished.",{exact:false}).waitFor({state:"visible"});
 await screen.getByRole("button","Stop generation").waitFor({state:"hidden"});
 const child=JSON.parse(fs.readFileSync(project+"/.recovery-proof.json","utf8"));
 const envId=fs.readFileSync(T3_HOME+"/userdata/environment-id","utf8").trim();
 await app.open("/"+envId+"/"+encodeURIComponent(child.childThreadId));
 await screen.getByRole("textbox").waitFor({state:"visible"});
 await screen.getByText("Remembered ORCHID-728. Child ready.",{exact:true}).waitFor({state:"visible"});
 await screen.getByText("Syncing messages...",{exact:false}).waitFor({state:"hidden"});
 await app.screenshot("child-conversation");
 await app.open("/"+envId+"/"+encodeURIComponent(threadId));
 await screen.getByRole("textbox").waitFor({state:"visible"});
 await send("PROOF_REPORT: show the completed recovery outcomes.");
 await screen.getByText("Evidence report ready.",{exact:false}).waitFor({state:"visible"});
 await screen.getByRole("button","Stop generation").waitFor({state:"hidden"});
 await screen.getByText("Evidence report ready.",{exact:false}).last().scrollIntoView();
 await app.screenshot("account-recovery");
 await expect(screen.getByText("Configure: success",{exact:false}).last()).toBeVisible();
 await expect(screen.getByText("Continue: success",{exact:false}).last()).toBeVisible();
 await expect(screen.getByText("History recall: ORCHID-728",{exact:false}).last()).toBeVisible();
});
