import { readFileSync, existsSync } from "node:fs";
import { homedir } from "node:os";
import { resolve } from "node:path";
import { resolveProviderKey } from "../../../security/key-store.js";
async function verifyEndToEnd(deps) {
  const [search, fetch, extract, synthesis] = await Promise.all([
    deps.probeSearch().catch((err) => ({
      capability: "search",
      status: "fail",
      detail: `probe threw: ${err instanceof Error ? err.message : String(err)}`
    })),
    deps.probeFetch().catch((err) => ({
      capability: "fetch",
      status: "fail",
      detail: `probe threw: ${err instanceof Error ? err.message : String(err)}`
    })),
    deps.probeExtract().catch((err) => ({
      capability: "extract",
      status: "fail",
      detail: `probe threw: ${err instanceof Error ? err.message : String(err)}`
    })),
    deps.probeSynthesis().catch((err) => ({
      capability: "synthesis",
      status: "fail",
      detail: `probe threw: ${err instanceof Error ? err.message : String(err)}`
    }))
  ]);
  const wiringResults = await deps.probeMcpWiring().catch(() => []);
  const mcpWiringCap = buildMcpWiringCapability(wiringResults);
  const capabilities = [search, fetch, extract, synthesis, mcpWiringCap];
  const hardFailureCount = capabilities.filter((c) => c.status === "fail").length;
  const allPassed = hardFailureCount === 0;
  return { capabilities, mcpWiringResults: wiringResults, allPassed, hardFailureCount };
}
function buildMcpWiringCapability(wiringResults) {
  if (wiringResults.length === 0) {
    return {
      capability: "mcp-wiring",
      status: "skipped",
      detail: "no agents configured \u2014 run `wigolo init` to wire an agent"
    };
  }
  const failed = wiringResults.filter((r) => r.status === "fail");
  if (failed.length === 0) {
    const names = wiringResults.map((r) => r.agentName).join(", ");
    return {
      capability: "mcp-wiring",
      status: "pass",
      detail: `wigolo entry confirmed in: ${names}`
    };
  }
  const failNames = failed.map((r) => `${r.agentName} (${r.detail})`).join("; ");
  return {
    capability: "mcp-wiring",
    status: "fail",
    detail: `MCP wiring missing for: ${failNames}`
  };
}
async function checkMcpWiringForAgent(input) {
  const { agentId, agentName, configPath, keyPath, installType, allowedRoots } = input;
  const base = {
    agentId,
    agentName,
    configPath
  };
  if (installType === "cli-command") {
    return { ...base, status: "pass", detail: "CLI-installed agent (no config file to check)" };
  }
  if (!configPath) {
    return { ...base, status: "fail", detail: "no configPath for agent \u2014 re-run `wigolo init`" };
  }
  if (!isPathWithinAllowedRoots(configPath, allowedRoots)) {
    return {
      ...base,
      status: "fail",
      detail: `config path is outside the home/working directory (${configPath}) \u2014 refusing to read`
    };
  }
  if (!existsSync(configPath)) {
    return {
      ...base,
      status: "fail",
      detail: `config file not found at ${configPath} \u2014 re-run \`wigolo init\` to create it`
    };
  }
  if (installType === "config-toml") {
    return checkTomlWiring(base, configPath, keyPath);
  }
  return checkJsonWiring(base, configPath, keyPath);
}
function isPathWithinAllowedRoots(configPath, allowedRoots) {
  const abs = resolve(configPath);
  const roots = (allowedRoots && allowedRoots.length > 0 ? allowedRoots : [homedir(), process.cwd()]).map((r) => resolve(r));
  return roots.some((root) => abs === root || abs.startsWith(root + "/"));
}
function checkJsonWiring(base, configPath, keyPath) {
  let parsed;
  try {
    const raw = readFileSync(configPath, "utf-8").trim();
    parsed = JSON.parse(raw);
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    return {
      ...base,
      status: "fail",
      detail: `could not parse config file: ${msg.slice(0, 80)} \u2014 re-run \`wigolo init\``
    };
  }
  const found = getAtPath(parsed, keyPath);
  if (found == null) {
    return {
      ...base,
      status: "fail",
      detail: `wigolo entry missing at ${keyPath.join(".")} \u2014 re-run \`wigolo init\` to repair`
    };
  }
  return { ...base, status: "pass", detail: "wigolo entry found" };
}
function checkTomlWiring(base, configPath, keyPath) {
  let raw;
  try {
    raw = readFileSync(configPath, "utf-8");
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    return {
      ...base,
      status: "fail",
      detail: `could not read config file: ${msg.slice(0, 80)} \u2014 re-run \`wigolo init\``
    };
  }
  const tableName = keyPath.join(".");
  const pattern = new RegExp(
    `^\\s*\\[\\s*${escapeRegex(tableName)}\\s*[\\].]`,
    "m"
  );
  if (!pattern.test(raw)) {
    return {
      ...base,
      status: "fail",
      detail: `wigolo entry missing at [${tableName}] \u2014 re-run \`wigolo init\` to repair`
    };
  }
  return { ...base, status: "pass", detail: "wigolo entry found" };
}
function getAtPath(obj, keyPath) {
  let cursor = obj;
  for (const key of keyPath) {
    if (cursor == null || typeof cursor !== "object" || Array.isArray(cursor)) return null;
    cursor = cursor[key];
  }
  return cursor ?? null;
}
function escapeRegex(s) {
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
const STABLE_FETCH_URL = "https://www.example.com";
const STABLE_SEARCH_QUERY = "wigolo mcp server";
async function buildDefaultDeps() {
  return {
    probeSearch: buildDefaultSearchProbe(),
    probeFetch: buildDefaultFetchProbe(),
    probeExtract: buildDefaultExtractProbe(),
    probeSynthesis: buildDefaultSynthesisProbe(),
    probeMcpWiring: buildDefaultMcpWiringProbe()
  };
}
function buildDefaultSearchProbe() {
  return async () => {
    try {
      const { getSearchProvider } = await import("../../../providers/search-provider.js");
      const provider = await getSearchProvider();
      const { buildMinimalRouter } = await import("./verify-router.js");
      const router = await buildMinimalRouter();
      const result = await provider.search(
        { query: STABLE_SEARCH_QUERY },
        { engines: [], router }
      );
      const count = result.ok ? result.data.results?.length ?? 0 : 0;
      if (!result.ok || count === 0) {
        return {
          capability: "search",
          status: "fail",
          detail: "search returned 0 results \u2014 check internet connectivity or WIGOLO_SEARCH env var"
        };
      }
      return { capability: "search", status: "pass", detail: `got ${count} result(s)` };
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      return {
        capability: "search",
        status: "fail",
        detail: `search probe failed: ${msg.slice(0, 120)} \u2014 check internet connectivity`
      };
    }
  };
}
function buildDefaultFetchProbe() {
  return async () => {
    try {
      const { buildMinimalRouter } = await import("./verify-router.js");
      const router = await buildMinimalRouter();
      const raw = await router.fetch(STABLE_FETCH_URL, { renderJs: "never" });
      const chars = raw.html?.length ?? 0;
      if (chars === 0) {
        return {
          capability: "fetch",
          status: "fail",
          detail: `fetch returned empty body for ${STABLE_FETCH_URL} \u2014 check internet connectivity`
        };
      }
      return { capability: "fetch", status: "pass", detail: `fetched ${chars} chars` };
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      return {
        capability: "fetch",
        status: "fail",
        detail: `fetch probe failed: ${msg.slice(0, 120)} \u2014 check internet connectivity or run \`wigolo warmup\``
      };
    }
  };
}
function buildDefaultExtractProbe() {
  return async () => {
    const PROBE_HTML = "<html><head><title>Wigolo Probe</title></head><body><p>Hello probe</p></body></html>";
    try {
      const { getExtractProvider } = await import("../../../providers/extract-provider.js");
      const provider = await getExtractProvider();
      const result = await provider.extract(PROBE_HTML, STABLE_FETCH_URL);
      const title = result.title ?? "";
      const content = result.markdown ?? "";
      if (!title && !content) {
        return {
          capability: "extract",
          status: "fail",
          detail: "extraction returned no title or content \u2014 run `wigolo warmup` to reinstall content extractor"
        };
      }
      return { capability: "extract", status: "pass", detail: `extracted title="${title.slice(0, 40)}"` };
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      return {
        capability: "extract",
        status: "fail",
        detail: `extract probe failed: ${msg.slice(0, 120)} \u2014 run \`wigolo warmup\` to reinstall content extractor`
      };
    }
  };
}
function buildDefaultSynthesisProbe() {
  const SYNTHESIS_SKIP_DETAIL = "no provider key configured \u2014 add a provider key via `wigolo config` (or set ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY) to enable synthesis";
  return async () => {
    const { getConfig } = await import("../../../config.js");
    const dataDir = getConfig().dataDir;
    const { allProviders } = await import("../../../integrations/cloud/llm/select.js");
    let keyedProvider = null;
    for (const provider of allProviders()) {
      const key = await resolveProviderKey(provider, { dataDir }).catch(() => void 0);
      if (key) {
        keyedProvider = provider;
        break;
      }
    }
    if (!keyedProvider) {
      return { capability: "synthesis", status: "skipped", detail: SYNTHESIS_SKIP_DETAIL };
    }
    try {
      const { selectProvider } = await import("../../../integrations/cloud/llm/select.js");
      const active = selectProvider(process.env) ?? keyedProvider;
      const { runLlmText } = await import("../../../integrations/cloud/llm/run.js");
      const response = await runLlmText({
        prompt: 'Reply with the single word "ok".',
        maxTokens: 10
      });
      const text = response.text?.trim() ?? "";
      if (!text) {
        return {
          capability: "synthesis",
          status: "fail",
          detail: `synthesis returned empty response \u2014 check your ${active.toUpperCase()} API key`
        };
      }
      return { capability: "synthesis", status: "pass", detail: `synthesis ok (${active})` };
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      return {
        capability: "synthesis",
        status: "fail",
        detail: `synthesis probe failed: ${msg.slice(0, 120)} \u2014 check your provider API key`
      };
    }
  };
}
function buildDefaultMcpWiringProbe() {
  return async () => {
    const { detectAgents } = await import("../agents.js");
    const { JSON_SPECS, CODEX_TABLE_PATH } = await import("../config-writer.js");
    const detected = detectAgents({});
    const configured = detected.filter((a) => a.detected);
    if (configured.length === 0) return [];
    const results = [];
    for (const agent of configured) {
      let keyPath;
      if (agent.installType === "cli-command") {
        keyPath = [];
      } else if (agent.installType === "config-toml") {
        keyPath = CODEX_TABLE_PATH;
      } else {
        const spec = JSON_SPECS[agent.id];
        keyPath = spec?.keyPath ?? [];
      }
      const r = await checkMcpWiringForAgent({
        agentId: agent.id,
        agentName: agent.displayName,
        configPath: agent.configPath,
        keyPath,
        installType: agent.installType
      });
      results.push(r);
    }
    return results;
  };
}
function formatVerifyResultPlain(result) {
  const lines = [];
  lines.push("[wigolo verify] Capability smoke check:");
  for (const cap of result.capabilities) {
    const label = cap.capability.padEnd(12);
    const statusTag = cap.status === "pass" ? "PASS" : cap.status === "skipped" ? "SKIP" : "FAIL";
    lines.push(`  ${statusTag}  ${label}  ${cap.detail}`);
  }
  if (result.mcpWiringResults.length > 0) {
    lines.push("");
    lines.push("[wigolo verify] MCP wiring:");
    for (const w of result.mcpWiringResults) {
      const statusTag = w.status === "pass" ? "PASS" : w.status === "skipped" ? "SKIP" : "FAIL";
      lines.push(`  ${statusTag}  ${w.agentName.padEnd(16)}  ${w.detail}`);
    }
  }
  lines.push("");
  if (result.allPassed) {
    lines.push("[wigolo verify] Overall: OK \u2014 all capabilities pass");
  } else {
    lines.push(
      `[wigolo verify] Overall: FAIL \u2014 ${result.hardFailureCount} hard failure(s) detected`
    );
  }
  return lines;
}
export {
  buildDefaultDeps,
  checkMcpWiringForAgent,
  formatVerifyResultPlain,
  verifyEndToEnd
};
//# sourceMappingURL=verify-e2e.js.map