import * as NetService from "@t3tools/shared/Net";
import * as NodeCrypto from "@effect/platform-node/NodeCrypto";
import * as FS from "node:fs/promises";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as References from "effect/References";
import * as EnvironmentAuth from "../../apps/server/src/auth/EnvironmentAuth.ts";
import * as ServerConfig from "../../apps/server/src/config.ts";
import { resolveCliAuthConfig } from "../../apps/server/src/cli/config.ts";
import { mcpToolSession } from "../../apps/server/src/mcp/AcpMcpStdioBridge.ts";
const PROOF_HOME = process.env.PROOF_HOME!;
const MOBILE = {serverPort:Number(process.env.PROOF_PORT)};
import { runPromise } from "./t3.ts";
import { makeState } from "./t3.ts";

const call = async (name: string, args: Record<string, unknown>) => runPromise(Effect.gen(function* () {
  const config = yield* resolveCliAuthConfig({baseDir: Option.some(PROOF_HOME)}, Option.none(), {quietLogs:true});
  return yield* Effect.gen(function* () {
    const auth = yield* EnvironmentAuth.EnvironmentAuth;
    const issued = yield* Effect.acquireRelease(auth.issueMcpClientSession({label:"Evidence driver",access:"full-access",peerLink:false,client:{deviceType:"bot"}}), s => auth.revokeSession(s.sessionId));
    const session = yield* mcpToolSession({endpoint:`http://127.0.0.1:${MOBILE.serverPort}/mcp`, authorization:`Bearer ${issued.token}`,clientName:"evidence-driver"});
    return yield* session.call(name,args);
  }).pipe(Effect.scoped, Effect.provide(EnvironmentAuth.layerRuntime.pipe(Layer.provide(ServerConfig.layer(config)),Layer.provide(Layer.succeed(References.MinimumLogLevel,"Error")))));
}).pipe(Effect.provide([NetService.layer, NodeCrypto.layer])));


const action = process.argv[2];
const {state} = makeState(PROOF_HOME, {T3CODE_PORT:String(MOBILE.serverPort)});
if(action === "seed") {
  await state.project("Accessibility demo");
  const projects: any = await call("t3_project_list",{});
  const projectId = projects.structuredContent.projects[0].id;
  const ids: Record<string,string> = {};
  for (const [title,model,message,mode] of [
    ["Finished thread","showcase","Show the demo","full-access"],
    ["Time-only thread","showcase",undefined,"full-access"],
    ["Approval thread","approval","Please make the edit","approval-required"],
    ["Working thread","command-output","Keep working","full-access"],
    ["Waiting thread","todo-list","Wait for a thread","full-access"],
  ]) {
    const result: any = await call("t3_thread_launch",{projectId,title,modelSelection:{instanceId:"devReplay",model},...(message ? {message}:{}),runtimeMode:mode});
    if(result.isError) throw new Error(JSON.stringify(result));
    ids[title!] = result.structuredContent.threadId;
    if(title === "Finished thread") await call("t3_thread_wait",{threadId:ids[title]});
  }
  await FS.writeFile(process.env.PROOF_STATE!,JSON.stringify(ids));
  console.log("Seeded finished, idle, approval, working, and waiting threads.");
} else {
  const ids = JSON.parse(await FS.readFile(process.env.PROOF_STATE!,"utf8"));
  const title = process.argv[3] || "Finished thread";
  const result: any = action === "wait" ? await call("t3_thread_wait", {threadId:ids[title]}) : ["restart","send"].includes(action) ? await call("t3_thread_send",{threadId:ids[title],message:"Continue the synthetic task",mode:action === "restart" ? "restart" : "auto"}) : await call("t3_thread_organize",{threadId:ids[title],action,...(action === "snooze" ? {snoozedUntil:new Date(Date.now()+Number(process.argv[4] || 3600)*1000).toISOString()}:{})});
  if(result.isError) throw new Error(JSON.stringify(result));
  console.log("Applied " + action);
}
