import assert from 'node:assert/strict';
import test from 'node:test';
import type { CallToolResult, McpServer } from '@modelcontextprotocol/server';
import { OrchestratorService } from '@platform-modules/chatgpt-orchestrator-core';
import { InMemoryRepository } from '@platform-modules/chatgpt-orchestrator-persistence';
import { createOrchestratorMcpServer } from '../src/server.js';

type RegisteredTool = { handler: (input: Record<string, unknown>) => Promise<CallToolResult> };
type InspectableMcpServer = { _registeredTools: Record<string, RegisteredTool> };

function tools(server: McpServer): Record<string, RegisteredTool> {
  return (server as unknown as InspectableMcpServer)._registeredTools;
}

function structured<T extends Record<string, unknown>>(result: CallToolResult): T {
  assert.notEqual(result.isError, true, JSON.stringify(result));
  assert.ok(result.structuredContent);
  return result.structuredContent as T;
}

test('MCP server constructs with the refined continuation schemas and exposes the Wave 1 continuity tools', () => {
  const service = new OrchestratorService(new InMemoryRepository());
  const server = createOrchestratorMcpServer(service);
  const names = Object.keys(tools(server));
  for (const name of [
    'run.continuation.get',
    'run.continuation.set_default',
    'worker.continuation.get',
    'worker.continuation.set',
    'worker.execution_attempts',
    'worker.await_human',
    'worker.await_dependency',
    'worker.pause',
    'worker.resume',
    'worker.continue_now',
  ]) assert.ok(names.includes(name), `${name} should be registered`);
});

test('MCP continuity tools drive the authoritative core without launching a duplicate root conversation', async () => {
  const service = new OrchestratorService(new InMemoryRepository());
  const server = createOrchestratorMcpServer(service);
  const registered = tools(server);

  const created = structured<{ run: { runId: string }; rootWorker: { workerId: string }; executionId: string }>(
    await registered['run.create']!.handler({ title: 'mcp continuity', idempotencyKey: 'mcp-run' }),
  );
  assert.match(created.executionId, /^exe_/);
  const rootAttempts = await service.listExecutionAttempts(created.rootWorker.workerId as `wrk_${string}`);
  assert.equal(rootAttempts.length, 1);
  assert.equal(rootAttempts[0]?.state, 'generating');
  assert.equal((await service.listDispatchableExecutorCommands()).length, 0);

  const replay = structured<{ executionId: string }>(
    await registered['run.create']!.handler({ title: 'mcp continuity', idempotencyKey: 'mcp-run' }),
  );
  assert.equal(replay.executionId, created.executionId);
  assert.equal((await service.listDispatchableExecutorCommands()).length, 0);

  const policy = structured<{ policy: { mode: string; idleGraceMs: number } }>(
    await registered['run.continuation.set_default']!.handler({
      runId: created.run.runId,
      policy: { mode: 'auto', idleGraceMs: 0 },
    }),
  );
  assert.equal(policy.policy.mode, 'auto');
  assert.equal(policy.policy.idleGraceMs, 0);

  const child = structured<{ worker: { workerId: string }; executionId: string; executorCommandId: string }>(
    await registered['worker.spawn']!.handler({
      runId: created.run.runId,
      parentWorkerId: created.rootWorker.workerId,
      name: 'mcp-child',
      assignment: { objective: 'exercise continuity controls' },
      idempotencyKey: 'mcp-child',
    }),
  );
  assert.match(child.executionId, /^exe_/);
  assert.match(child.executorCommandId, /^cmd_/);
  assert.equal((await service.listDispatchableExecutorCommands()).length, 1);

  const paused = structured<{ continuity: { disposition: string } }>(
    await registered['worker.pause']!.handler({ workerId: child.worker.workerId }),
  );
  assert.equal(paused.continuity.disposition, 'paused');

  const resumed = structured<{ continuity: { disposition: string } }>(
    await registered['worker.resume']!.handler({ workerId: child.worker.workerId }),
  );
  assert.equal(resumed.continuity.disposition, 'awaiting_execution');
});
