import { expect } from "e2e";
import * as fs from "node:fs/promises";
import { watch } from "node:fs";
import path from "node:path";
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 NetService from "@t3tools/shared/Net";
import * as NodeCrypto from "@effect/platform-node/NodeCrypto";
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 T3_HOME = process.argv[2]!;
import { run } from "./shell.ts";
import { makeState, runPromise } from "./t3.ts";

async function tools<A>(use: (call: (name: string, args: Record<string, unknown>) => Effect.Effect<any, any>) => Effect.Effect<A, any>) {
  return runPromise(Effect.gen(function* () {
    const config = yield* resolveCliAuthConfig({baseDir: Option.some(T3_HOME)}, Option.none());
    return yield* Effect.gen(function* () {
      const auth = yield* EnvironmentAuth.EnvironmentAuth;
      const issued = yield* Effect.acquireRelease(
        auth.issueMcpClientSession({label: "Cleanup scenario", access: "full-access", peerLink: false, client: {deviceType: "bot"}}),
        session => auth.revokeSession(session.sessionId).pipe(Effect.ignore),
      );
      const runtime = JSON.parse(awaitableRuntime);
      const session = yield* mcpToolSession({endpoint: new URL("/mcp", runtime.origin).href, authorization: `Bearer ${issued.token}`, clientName: "cleanup-scenario"});
      return yield* use((name, args) => session.call(name,args).pipe(Effect.map((raw: any) => {
        if (raw.isError) throw new Error(JSON.stringify(raw));
        return raw.structuredContent;
      })));
    }).pipe(Effect.scoped, Effect.provide(EnvironmentAuth.layerRuntime.pipe(Layer.provide(ServerConfig.layer(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, config.logLevel)))));
  }).pipe(Effect.provide([NetService.layer, NodeCrypto.layer])));
}
let awaitableRuntime = "";

const t3 = makeState(T3_HOME).state;
  const project = await t3.project("cleanup-demo", {"README.md": "Synthetic cleanup demonstration\n"});
  const parent = path.join(T3_HOME,"worktrees","cleanup-demo");
  const shared = path.join(parent,"shared-checkout");
  const control = path.join(parent,"single-thread-control");
  const alias = path.join(T3_HOME,"linked-parent");
  await fs.mkdir(parent,{recursive:true});
  await fs.symlink(parent,alias,"dir");
  for (const [folder,branch] of [[shared,"shared-checkout"],[control,"single-thread-control"]]) {
    await runPromise(run("git",["worktree","add","-b",branch!,folder!,"main"],{cwd:project}));
  }
  awaitableRuntime = await fs.readFile(path.join(T3_HOME,"userdata/server-runtime.json"),"utf8");
  await tools(call => Effect.gen(function* () {
    const listed = yield* call("t3_project_list",{});
    const projectId = listed.projects.find((p: any) => p.workspaceRoot === project).id;
    for (const [title, worktreePath, branch] of [
      ["Shared checkout · physical path",shared,"shared-checkout"],
      ["Shared checkout · linked parent",path.join(alias,"shared-checkout"),"shared-checkout"],
      ["Single-thread removal control",control,"single-thread-control"],
    ]) {
      const launched = yield* call("t3_thread_launch",{projectId,title,workspaceStrategy:{type:"existing_worktree",worktreePath,branch},message:"Complete this demonstration turn without changing files.", modelSelection:{instanceId:"devReplay",model:"multi-turn"}});
      const result = yield* call("t3_thread_wait",{threadId:launched.threadId,runId:launched.runId,timeoutMs:120000});
      console.log(JSON.stringify({title,threadId:launched.threadId,result}));
    }
  }));
console.log(JSON.stringify({project,shared,control,alias}));
