import process from "node:process";
import { resolveDebugProxySettings, type DebugProxySettings } from "./env.js";
import type { CaptureProtocol } from "./types.js";

export type DebugProxyCoverageStatus = "captured" | "proxy-only" | "uncovered";

export type DebugProxyCoverageEntry = {
  id: string;
  label: string;
  modulePath: string;
  protocols: CaptureProtocol[];
  status: DebugProxyCoverageStatus;
  notes: string;
};

export type DebugProxyCoverageSummary = {
  total: number;
  captured: number;
  proxyOnly: number;
  uncovered: number;
};

const DEBUG_PROXY_COVERAGE_ENTRIES: readonly DebugProxyCoverageEntry[] = [
  {
    id: "provider-transport-fetch",
    label: "Provider HTTP transport",
    modulePath: "src/agents/provider-transport-fetch.ts",
    protocols: ["http", "https", "sse"],
    status: "captured",
    notes:
      "Central provider fetch seam routes through explicit proxy overrides and records request/response payloads.",
  },
  {
    id: "openai-ws-manager",
    label: "OpenAI websocket manager",
    modulePath: "src/agents/openai-ws-connection.ts",
    protocols: ["ws", "wss"],
    status: "captured",
    notes:
      "Central OpenAI websocket path records open/frame/close/error events with proxy agent support.",
  },
  {
    id: "discord-rest",
    label: "Discord REST monitor fetch",
    modulePath: "extensions/discord/monitor/rest-fetch.ts",
    protocols: ["http", "https"],
    status: "captured",
    notes: "Discord monitor REST calls inherit the debug proxy and record HTTP exchanges.",
  },
  {
    id: "discord-gateway",
    label: "Discord gateway monitor",
    modulePath: "extensions/discord/monitor/gateway-plugin.ts",
    protocols: ["https", "wss"],
    status: "captured",
    notes:
      "Gateway metadata fetches and websocket lifecycle events are captured for monitor traffic.",
  },
  {
    id: "telegram-fetch",
    label: "Telegram fetch resolver",
    modulePath: "extensions/telegram/fetch.ts",
    protocols: ["http", "https"],
    status: "captured",
    notes:
      "Telegram API fetch fallback picks up debug proxy env and records outbound/inbound exchanges.",
  },
  {
    id: "mattermost-ws",
    label: "Mattermost monitor websocket",
    modulePath: "extensions/mattermost/mattermost/monitor-websocket.ts",
    protocols: ["ws", "wss"],
    status: "captured",
    notes: "Mattermost websocket monitor uses the debug proxy agent and records frame activity.",
  },
  {
    id: "openai-realtime-voice",
    label: "OpenAI realtime voice bridge",
    modulePath: "extensions/openai/realtime-voice-provider.ts",
    protocols: ["wss"],
    status: "captured",
    notes:
      "Realtime voice bridge now routes through the debug proxy agent and records websocket frames.",
  },
  {
    id: "openai-realtime-transcription",
    label: "OpenAI realtime transcription",
    modulePath: "extensions/openai/realtime-transcription-provider.ts",
    protocols: ["wss"],
    status: "captured",
    notes:
      "Realtime transcription sessions now route through the debug proxy agent and record websocket frames.",
  },
  {
    id: "openai-tts",
    label: "OpenAI text-to-speech",
    modulePath: "extensions/openai/tts.ts",
    protocols: ["https"],
    status: "captured",
    notes:
      "Direct OpenAI TTS fetches record request/response payloads while inheriting proxy env routing.",
  },
  {
    id: "microsoft-voices",
    label: "Microsoft voice discovery",
    modulePath: "extensions/microsoft/speech-provider.ts",
    protocols: ["https"],
    status: "captured",
    notes:
      "Microsoft voice listing fetches record HTTP exchanges and follow process-wide proxy routing.",
  },
  {
    id: "feishu-client-http",
    label: "Feishu SDK HTTP client",
    modulePath: "extensions/feishu/client.ts",
    protocols: ["https"],
    status: "proxy-only",
    notes:
      "Feishu SDK traffic can inherit ambient proxying, but decrypted request/response capture is not yet wired at the SDK seam.",
  },
  {
    id: "feishu-client-ws",
    label: "Feishu SDK websocket client",
    modulePath: "extensions/feishu/client.ts",
    protocols: ["wss"],
    status: "proxy-only",
    notes:
      "Feishu websocket creation can inherit ambient proxying, but websocket frame capture is not yet wired.",
  },
];

let warnedCoverageSessionKey: string | null = null;

export function listDebugProxyCoverageEntries(): DebugProxyCoverageEntry[] {
  return DEBUG_PROXY_COVERAGE_ENTRIES.map((entry) => ({
    ...entry,
    protocols: [...entry.protocols],
  }));
}

export function summarizeDebugProxyCoverage(
  entries: readonly DebugProxyCoverageEntry[] = DEBUG_PROXY_COVERAGE_ENTRIES,
): DebugProxyCoverageSummary {
  let captured = 0;
  let proxyOnly = 0;
  let uncovered = 0;
  for (const entry of entries) {
    if (entry.status === "captured") {
      captured += 1;
      continue;
    }
    if (entry.status === "proxy-only") {
      proxyOnly += 1;
      continue;
    }
    uncovered += 1;
  }
  return {
    total: entries.length,
    captured,
    proxyOnly,
    uncovered,
  };
}

export function buildDebugProxyCoverageReport() {
  const entries = listDebugProxyCoverageEntries();
  return {
    summary: summarizeDebugProxyCoverage(entries),
    entries,
  };
}

export function maybeWarnAboutDebugProxyCoverage(
  settings: DebugProxySettings = resolveDebugProxySettings(),
  warn: (message: string) => void = (message) => process.stderr.write(`${message}\n`),
): void {
  if (!settings.enabled || !settings.required) {
    return;
  }
  const sessionKey = `${settings.sessionId}:${settings.proxyUrl ?? ""}`;
  if (warnedCoverageSessionKey === sessionKey) {
    return;
  }
  warnedCoverageSessionKey = sessionKey;

  const report = buildDebugProxyCoverageReport();
  const { summary } = report;
  const partial = report.entries.filter((entry) => entry.status !== "captured");
  if (partial.length === 0) {
    return;
  }
  warn(
    `[openclaw proxy] debug proxy coverage: ${summary.captured}/${summary.total} captured, ${summary.proxyOnly} proxy-only, ${summary.uncovered} uncovered.`,
  );
  warn(
    `[openclaw proxy] remaining gaps: ${partial.map((entry) => entry.id).join(", ")}. Run \`openclaw proxy coverage\` for details.`,
  );
}
