import { test } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { EXPECTED_AI_TOOLS, registeredMcpTools } from "./parity-test.ts";

const here = path.dirname(fileURLToPath(import.meta.url));
const mcpSrc = fs.readFileSync(path.join(here, "..", "dewx-mcp.ts"), "utf8");

test("AI MCP tools are registered with ai_generate wired through LocalDB", () => {
  const registered = registeredMcpTools(mcpSrc);
  for (const tool of EXPECTED_AI_TOOLS) assert.equal(registered.has(tool), true);
  assert.match(mcpSrc, /server\.tool\("ai_generate"/);
  assert.match(mcpSrc, /createAiRequest/);
  assert.match(mcpSrc, /waitForAiRequest/);
  assert.match(mcpSrc, /table:\s*"ai_requests"/);
  assert.doesNotMatch(mcpSrc, /stubbed_/);
  assert.doesNotMatch(mcpSrc, /mlx-community\/Qwen3/);
  assert.match(mcpSrc, /Apple Intelligence/);
  assert.match(mcpSrc, /Codex CLI/);
});

test("P1 AI wrapper contract is draft-only and does not call send_message", () => {
  const generateBlock = toolBlock("ai_generate");
  const draftBlock = toolBlock("ai_draft_reply");
  const rewriteBlock = toolBlock("ai_rewrite_text");
  assert.doesNotMatch(generateBlock, /send_message/);
  assert.doesNotMatch(generateBlock, /websync\.sendReply/);
  assert.doesNotMatch(generateBlock, /outbound_draft/);
  for (const block of [draftBlock, rewriteBlock]) {
    assert.match(block, /draft_only:\s*true/);
    assert.match(block, /send_side_effect:\s*false/);
    assert.match(block, /createAiRequest|runAiBridgeTool/);
    assert.doesNotMatch(block, /send_message/);
    assert.doesNotMatch(block, /websync\.sendReply/);
    assert.doesNotMatch(block, /outbound_draft/);
  }
});

test("destubbed AI wrappers queue bridge requests with typed prompts", () => {
  for (const name of ["ai_summarize_thread", "ai_draft_reply", "ai_rewrite_text", "ai_transcribe_audio"]) {
    const block = toolBlock(name);
    assert.match(block, /withDbAsync/);
    assert.match(block, /runAiBridgeTool/);
    assert.doesNotMatch(block, /planned_loopback_contract/);
  }
  assert.match(toolBlock("ai_summarize_thread"), /jsonPrompt\("summarize_thread"/);
  assert.match(toolBlock("ai_draft_reply"), /jsonPrompt\("draft_reply"/);
  assert.match(toolBlock("ai_rewrite_text"), /jsonPrompt\("rewrite_text"/);
  assert.match(toolBlock("ai_transcribe_audio"), /jsonPrompt\("transcribe"/);
  assert.doesNotMatch(toolBlock("ai_transcribe_audio"), /whisperkit-coreml:<variant>/);
});

function toolBlock(name: string): string {
  const start = mcpSrc.indexOf(`server.tool("${name}"`);
  assert.notEqual(start, -1, `${name} missing`);
  const next = mcpSrc.indexOf("\n  server.tool(", start + 1);
  return mcpSrc.slice(start, next === -1 ? undefined : next);
}
