// Scratch repro driver for pingdotgg/t3code#26515. Run from apps/server:
//   node outside-mcp-driver.ts <baseDir>
// Signs in as a full-access mcp-client (like an outside agent, no thread),
// then calls tools over /mcp and prints each result.
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
import * as NodeServices from "@effect/platform-node/NodeServices";
import * as NetService from "@t3tools/shared/Net";
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 "./src/auth/EnvironmentAuth.ts";
import * as ServerConfig from "./src/config.ts";
import { resolveCliAuthConfig } from "./src/cli/config.ts";
import { readPersistedServerRuntimeState } from "./src/serverRuntimeState.ts";

const baseDir = process.argv[2]!;
const program = Effect.gen(function* () {
  const config = yield* resolveCliAuthConfig({ baseDir: Option.some(baseDir) }, Option.none());
  return yield* Effect.gen(function* () {
    const state = yield* readPersistedServerRuntimeState(config.serverRuntimeStatePath);
    const origin = Option.getOrThrow(state).origin;
    const auth = yield* EnvironmentAuth.EnvironmentAuth;
    const issued = yield* Effect.acquireRelease(
      auth.issueMcpClientSession({
        label: "issue-26515 repro",
        access: "full-access",
        peerLink: false,
        client: { deviceType: "bot" },
      }),
      (s) => auth.revokeSession(s.sessionId).pipe(Effect.ignore),
    );
    yield* Effect.promise(() => run(new URL("/mcp", origin).href, issued.token));
  }).pipe(
    Effect.scoped,
    Effect.provide(
      EnvironmentAuth.layerRuntime.pipe(
        Layer.provide(ServerConfig.layer(config)),
        Layer.provide(Layer.succeed(References.MinimumLogLevel, config.logLevel)),
      ),
    ),
  );
});

async function run(endpoint: string, token: string) {
  let session: string | null = null;
  let id = 0;
  const rpc = async (method: string, params: unknown) => {
    const res = await fetch(endpoint, {
      method: "POST",
      headers: {
        authorization: `Bearer ${token}`,
        "content-type": "application/json",
        accept: "application/json, text/event-stream",
        ...(session ? { "mcp-session-id": session, "mcp-protocol-version": "2025-06-18" } : {}),
      },
      body: JSON.stringify({ jsonrpc: "2.0", id: ++id, method, params }),
    });
    session ??= res.headers.get("mcp-session-id");
    const text = await res.text();
    const line = text.split("\n").find((l) => l.startsWith("data:"));
    return JSON.parse(line ? line.slice(5) : text);
  };
  await rpc("initialize", {
    protocolVersion: "2025-06-18",
    capabilities: {},
    clientInfo: { name: "issue-26515-repro", version: "0" },
  });
  const list = await rpc("tools/list", {});
  const names: string[] = list.result.tools.map((t: { name: string }) => t.name).sort();
  console.log(`tools/list (${names.length}): ${names.join(", ")}`);
  const calls: Array<[string, Record<string, unknown>]> = [
    ["create_threads", { threads: [{ prompt: "hi" }] }],
    ["delegate_task", { task: "hi" }],
    ["task_status", { taskId: "x" }],
    ["html_render", { html: "<p>x</p>", title: "x", height: 80 }],
    ["t3_worktree_status", {}],
    ["preview_status", {}],
    ["t3_thread_list", {}],
    ["t3_thread_list", { allProjects: true }],
    ["t3_thread_search", { query: "x" }],
  ];
  for (const [tool, args] of calls) {
    const r = await rpc("tools/call", { name: tool, arguments: args });
    const out = r.result?.structuredContent ?? r.result?.content ?? r.error;
    console.log(`\n> ${tool} ${JSON.stringify(args)}\n${JSON.stringify(out)}`);
  }
}

program.pipe(Effect.provide(Layer.mergeAll(NodeServices.layer, NetService.layer)), NodeRuntime.runMain);
