import { vi, type Mock } from "vitest";
import type { PluginMetadataSnapshot } from "../../plugins/plugin-metadata-snapshot.js";
import { clearAgentHarnesses } from "../harness/registry.js";
import type { AgentRuntimePlan, BuildAgentRuntimePlanParams } from "../runtime-plan/types.js";
import type { CompactionTranscriptRotation } from "./compaction-successor-transcript.js";

type MockResolvedModel = {
  model: { provider: string; api: string; id: string; input: unknown[] };
  error: null;
  authStorage: { setRuntimeApiKey: Mock<(provider?: string, apiKey?: string) => void> };
  modelRegistry: Record<string, never>;
};
type MockMemorySearchManager = {
  manager: {
    sync: (params?: unknown) => Promise<void>;
  };
};
type MockEmbeddedAgentStreamFn = Mock<
  (model?: unknown, context?: unknown, options?: unknown) => unknown
>;

export const contextEngineCompactMock = vi.fn(async () => ({
  ok: true as boolean,
  compacted: true as boolean,
  reason: undefined as string | undefined,
  result: { summary: "engine-summary", tokensAfter: 50 } as
    | { summary: string; tokensAfter: number }
    | undefined,
}));

export const hookRunner = {
  hasHooks: vi.fn<(hookName?: string) => boolean>(),
  runBeforeCompaction: vi.fn(async () => undefined),
  runAfterCompaction: vi.fn(async () => undefined),
};

export const ensureRuntimePluginsLoaded: Mock<(params?: unknown) => void> = vi.fn();
export const resolveContextEngineMock = vi.fn(async () => ({
  info: { ownsCompaction: true as boolean },
  compact: contextEngineCompactMock,
}));
export const resolveModelMock: Mock<
  (provider?: string, modelId?: string, agentDir?: string, cfg?: unknown) => MockResolvedModel
> = vi.fn((_provider?: string, _modelId?: string, _agentDir?: string, _cfg?: unknown) => ({
  model: { provider: "openai", api: "responses", id: "fake", input: [] },
  error: null,
  authStorage: { setRuntimeApiKey: vi.fn() },
  modelRegistry: {},
}));
export const sessionCompactImpl = vi.fn(async () => ({
  summary: "summary",
  firstKeptEntryId: "entry-1",
  tokensBefore: 120,
  details: { ok: true },
}));
export const triggerInternalHook: Mock<(event?: unknown) => void> = vi.fn();
export const sanitizeSessionHistoryMock = vi.fn(
  async (params: { messages: unknown[] }) => params.messages,
);
export const getMemorySearchManagerMock: Mock<
  (params?: unknown) => Promise<MockMemorySearchManager>
> = vi.fn(async () => ({
  manager: {
    sync: vi.fn(async (_params?: unknown) => {}),
  },
}));
export const resolveMemorySearchConfigMock = vi.fn(() => ({
  sources: ["sessions"],
  sync: {
    sessions: {
      postCompactionForce: true,
    },
  },
}));
export const resolveSessionAgentIdMock = vi.fn(() => "main");
export const resolveSessionAgentIdsMock = vi.fn(() => ({
  defaultAgentId: "main",
  sessionAgentId: "main",
}));
export const estimateTokensMock = vi.fn((_message?: unknown) => 10);
export const resolveAgentHarnessPolicyMock = vi.fn(() => ({ runtime: "pi" }));
export const resolveContextWindowInfoMock = vi.fn(() => ({ tokens: 128_000 }));
function createDefaultSessionMessages(): unknown[] {
  return [
    { role: "user", content: "hello", timestamp: 1 },
    { role: "assistant", content: [{ type: "text", text: "hi" }], timestamp: 2 },
    {
      role: "toolResult",
      toolCallId: "t1",
      toolName: "exec",
      content: [{ type: "text", text: "output" }],
      isError: false,
      timestamp: 3,
    },
  ];
}
export const sessionMessages: unknown[] = createDefaultSessionMessages();
export const sessionAbortCompactionMock: Mock<(reason?: unknown) => void> = vi.fn();
export const createOpenClawCodingToolsMock = vi.fn(() => []);
export const guardSessionManagerMock = vi.fn(() => ({
  flushPendingToolResults: vi.fn(),
}));
export const applyPiCompactionSettingsFromConfigMock = vi.fn();
export const createPreparedEmbeddedPiSettingsManagerMock = vi.fn(() => ({
  getGlobalSettings: vi.fn(() => ({})),
}));
export const listRegisteredPluginAgentPromptGuidanceMock = vi.fn((params?: { surface?: string }) =>
  params?.surface === "subagent"
    ? ["Subagent compact command guidance."]
    : params?.surface === "acp_backend"
      ? ["ACP compact command guidance."]
      : ["Main compact command guidance."],
);
export const buildEmbeddedSystemPromptMock = vi.fn(() => "");
export const resolveEmbeddedAgentStreamFnMock: Mock<
  (params?: unknown) => MockEmbeddedAgentStreamFn
> = vi.fn((_params?: unknown) => vi.fn());
export const registerProviderStreamForModelMock: Mock<(params?: unknown) => unknown> = vi.fn();
export const applyExtraParamsToAgentMock = vi.fn(() => ({ effectiveExtraParams: {} }));
export const resolveAgentTransportOverrideMock: Mock<(params?: unknown) => string | undefined> =
  vi.fn(() => undefined);
export const resolveSandboxContextMock = vi.fn(async () => null);
export const maybeCompactAgentHarnessSessionMock: Mock<(params?: unknown) => Promise<unknown>> =
  vi.fn(async () => undefined);
export const rotateTranscriptAfterCompactionMock: Mock<
  (_params?: unknown) => Promise<CompactionTranscriptRotation>
> = vi.fn(async () => ({
  rotated: false,
}));
export const enqueueCommandInLaneMock = vi.fn((_lane: unknown, task: () => unknown) => task());

function createCompactHooksRuntimePlan(params: BuildAgentRuntimePlanParams): AgentRuntimePlan {
  const modelApi = params.modelApi ?? params.model?.api ?? undefined;
  const transcriptPolicy = {
    sanitizeMode: "full" as const,
    sanitizeToolCallIds: false,
    preserveNativeAnthropicToolUseIds: false,
    repairToolUseResultPairing: false,
    preserveSignatures: false,
    sanitizeThinkingSignatures: false,
    dropThinkingBlocks: false,
    applyGoogleTurnOrdering: false,
    validateGeminiTurns: false,
    validateAnthropicTurns: false,
    allowSyntheticToolResults: false,
  };

  return {
    resolvedRef: {
      provider: params.provider,
      modelId: params.modelId,
      ...(modelApi ? { modelApi } : {}),
      ...(params.resolvedTransport ? { transport: params.resolvedTransport } : {}),
    },
    auth: {
      providerForAuth: params.provider,
      authProfileProviderForAuth: params.authProfileProvider ?? params.provider,
      ...(params.sessionAuthProfileId
        ? { forwardedAuthProfileId: params.sessionAuthProfileId }
        : {}),
    },
    prompt: {
      provider: params.provider,
      modelId: params.modelId,
      resolveSystemPromptContribution: vi.fn(() => undefined),
      transformSystemPrompt: vi.fn((context: { systemPrompt: string }) => context.systemPrompt),
    },
    tools: {
      preparedPlanning: {
        loadMetadataSnapshot: () => ({}),
      },
      normalize: vi.fn((tools) => tools),
      logDiagnostics: vi.fn(),
    },
    transcript: {
      policy: transcriptPolicy,
      resolvePolicy: vi.fn(() => transcriptPolicy),
    },
    delivery: {
      isSilentPayload: vi.fn(() => false),
      resolveFollowupRoute: vi.fn(() => undefined),
    },
    outcome: {
      classifyRunResult: vi.fn(() => null),
    },
    transport: {
      extraParams: {},
      resolveExtraParams: vi.fn(() => ({})),
    },
    observability: {
      resolvedRef: `${params.provider}/${params.modelId}`,
      provider: params.provider,
      modelId: params.modelId,
      ...(modelApi ? { modelApi } : {}),
      ...(params.sessionAuthProfileId ? { authProfileId: params.sessionAuthProfileId } : {}),
      ...(params.resolvedTransport ? { transport: params.resolvedTransport } : {}),
    },
  };
}

const emptyPluginMetadataSnapshot: PluginMetadataSnapshot = {
  policyHash: "",
  index: {
    version: 1,
    hostContractVersion: "test",
    compatRegistryVersion: "test",
    migrationVersion: 1,
    policyHash: "",
    generatedAtMs: 1,
    installRecords: {},
    plugins: [],
    diagnostics: [],
  },
  registryDiagnostics: [],
  manifestRegistry: { plugins: [], diagnostics: [] },
  plugins: [],
  diagnostics: [],
  byPluginId: new Map(),
  normalizePluginId: (pluginId: string) => pluginId,
  owners: {
    channels: new Map(),
    channelConfigs: new Map(),
    providers: new Map(),
    modelCatalogProviders: new Map(),
    cliBackends: new Map(),
    setupProviders: new Map(),
    commandAliases: new Map(),
    contracts: new Map(),
  },
  metrics: {
    registrySnapshotMs: 0,
    manifestRegistryMs: 0,
    ownerMapsMs: 0,
    totalMs: 0,
    indexPluginCount: 0,
    manifestPluginCount: 0,
  },
};

export function resetCompactSessionStateMocks(): void {
  sanitizeSessionHistoryMock.mockReset();
  sanitizeSessionHistoryMock.mockImplementation(async (params: { messages: unknown[] }) => {
    return params.messages;
  });

  getMemorySearchManagerMock.mockReset();
  getMemorySearchManagerMock.mockResolvedValue({
    manager: {
      sync: vi.fn(async () => {}),
    },
  });
  resolveMemorySearchConfigMock.mockReset();
  resolveMemorySearchConfigMock.mockReturnValue({
    sources: ["sessions"],
    sync: {
      sessions: {
        postCompactionForce: true,
      },
    },
  });
  resolveSessionAgentIdMock.mockReset();
  resolveSessionAgentIdMock.mockReturnValue("main");
  resolveSessionAgentIdsMock.mockReset();
  resolveSessionAgentIdsMock.mockReturnValue({ defaultAgentId: "main", sessionAgentId: "main" });
  estimateTokensMock.mockReset();
  estimateTokensMock.mockReturnValue(10);
  sessionMessages.splice(0, sessionMessages.length, ...createDefaultSessionMessages());
  sessionAbortCompactionMock.mockReset();
  resolveEmbeddedAgentStreamFnMock.mockReset();
  resolveEmbeddedAgentStreamFnMock.mockImplementation((_params?: unknown) => vi.fn());
  registerProviderStreamForModelMock.mockReset();
  registerProviderStreamForModelMock.mockReturnValue(undefined);
  applyExtraParamsToAgentMock.mockReset();
  applyExtraParamsToAgentMock.mockReturnValue({ effectiveExtraParams: {} });
  resolveAgentTransportOverrideMock.mockReset();
  resolveAgentTransportOverrideMock.mockReturnValue(undefined);
  resolveSandboxContextMock.mockReset();
  resolveSandboxContextMock.mockResolvedValue(null);
  maybeCompactAgentHarnessSessionMock.mockReset();
  maybeCompactAgentHarnessSessionMock.mockResolvedValue(undefined);
  rotateTranscriptAfterCompactionMock.mockReset();
  rotateTranscriptAfterCompactionMock.mockResolvedValue({ rotated: false });
  enqueueCommandInLaneMock.mockReset();
  enqueueCommandInLaneMock.mockImplementation((_lane: unknown, task: () => unknown) => task());
  listRegisteredPluginAgentPromptGuidanceMock.mockReset();
  listRegisteredPluginAgentPromptGuidanceMock.mockImplementation((params?: { surface?: string }) =>
    params?.surface === "subagent"
      ? ["Subagent compact command guidance."]
      : params?.surface === "acp_backend"
        ? ["ACP compact command guidance."]
        : ["Main compact command guidance."],
  );
  buildEmbeddedSystemPromptMock.mockReset();
  buildEmbeddedSystemPromptMock.mockReturnValue("");
}

export function resetCompactHooksHarnessMocks(): void {
  clearAgentHarnesses();
  hookRunner.hasHooks.mockReset();
  hookRunner.hasHooks.mockReturnValue(false);
  hookRunner.runBeforeCompaction.mockReset();
  hookRunner.runBeforeCompaction.mockResolvedValue(undefined);
  hookRunner.runAfterCompaction.mockReset();
  hookRunner.runAfterCompaction.mockResolvedValue(undefined);

  ensureRuntimePluginsLoaded.mockReset();

  resolveContextEngineMock.mockReset();
  resolveContextEngineMock.mockResolvedValue({
    info: { ownsCompaction: true },
    compact: contextEngineCompactMock,
  });
  contextEngineCompactMock.mockReset();
  contextEngineCompactMock.mockResolvedValue({
    ok: true,
    compacted: true,
    reason: undefined,
    result: { summary: "engine-summary", tokensAfter: 50 },
  });

  resolveModelMock.mockReset();
  resolveModelMock.mockReturnValue({
    model: { provider: "openai", api: "responses", id: "fake", input: [] },
    error: null,
    authStorage: { setRuntimeApiKey: vi.fn() },
    modelRegistry: {},
  });
  resolveAgentHarnessPolicyMock.mockReset();
  resolveAgentHarnessPolicyMock.mockReturnValue({ runtime: "pi" });
  resolveContextWindowInfoMock.mockReset();
  resolveContextWindowInfoMock.mockReturnValue({ tokens: 128_000 });

  sessionCompactImpl.mockReset();
  sessionCompactImpl.mockResolvedValue({
    summary: "summary",
    firstKeptEntryId: "entry-1",
    tokensBefore: 120,
    details: { ok: true },
  });

  triggerInternalHook.mockReset();
  resetCompactSessionStateMocks();
  createOpenClawCodingToolsMock.mockReset();
  createOpenClawCodingToolsMock.mockReturnValue([]);
  guardSessionManagerMock.mockReset();
  guardSessionManagerMock.mockReturnValue({
    flushPendingToolResults: vi.fn(),
  });
  applyPiCompactionSettingsFromConfigMock.mockReset();
  createPreparedEmbeddedPiSettingsManagerMock.mockReset();
  createPreparedEmbeddedPiSettingsManagerMock.mockReturnValue({
    getGlobalSettings: vi.fn(() => ({})),
  });
}

export async function loadCompactHooksHarness(): Promise<{
  compactEmbeddedPiSessionDirect: typeof import("./compact.js").compactEmbeddedPiSessionDirect;
  compactEmbeddedPiSession: typeof import("./compact.queued.js").compactEmbeddedPiSession;
  testing: typeof import("./compact.js").testing;
  onSessionTranscriptUpdate: typeof import("../../sessions/transcript-events.js").onSessionTranscriptUpdate;
}> {
  resetCompactHooksHarnessMocks();
  vi.resetModules();

  vi.doMock("../../plugins/hook-runner-global.js", () => ({
    getGlobalHookRunner: () => hookRunner,
    getGlobalPluginRegistry: vi.fn(() => null),
    hasGlobalHooks: vi.fn(() => false),
    initializeGlobalHookRunner: vi.fn(),
    resetGlobalHookRunner: vi.fn(),
    runGlobalGatewayStopSafely: vi.fn(async () => undefined),
  }));

  vi.doMock("../runtime-plugins.js", () => ({
    ensureRuntimePluginsLoaded,
  }));

  vi.doMock("../../plugins/current-plugin-metadata-snapshot.js", () => ({
    captureCurrentPluginMetadataSnapshotState: vi.fn(() => ({
      snapshot: undefined,
      configFingerprint: undefined,
      compatiblePolicyHashes: undefined,
      compatibleConfigFingerprints: undefined,
    })),
    clearCurrentPluginMetadataSnapshot: vi.fn(),
    getCurrentPluginMetadataSnapshot: () => emptyPluginMetadataSnapshot,
    resolvePluginMetadataControlPlaneFingerprint: vi.fn(() => "test-plugin-fingerprint"),
    restoreCurrentPluginMetadataSnapshotState: vi.fn(),
    setCurrentPluginMetadataSnapshot: vi.fn(),
  }));

  vi.doMock("../../plugins/command-registry-state.js", () => {
    const pluginCommands = new Map<string, unknown>();
    return {
      clearPluginCommands: vi.fn(() => pluginCommands.clear()),
      clearPluginCommandsForPlugin: vi.fn(),
      isPluginCommandRegistryLocked: vi.fn(() => false),
      isTrustedReservedCommandOwner: vi.fn(() => false),
      listRegisteredPluginCommands: vi.fn(() => []),
      listRegisteredPluginAgentPromptGuidance: listRegisteredPluginAgentPromptGuidanceMock,
      pluginCommands,
      restorePluginCommands: vi.fn(),
      setPluginCommandRegistryLocked: vi.fn(),
    };
  });

  vi.doMock("../harness/selection.js", () => ({
    maybeCompactAgentHarnessSession: maybeCompactAgentHarnessSessionMock,
    resolveAgentHarnessPolicy: resolveAgentHarnessPolicyMock,
  }));

  vi.doMock("../../plugins/provider-runtime.js", () => ({
    prepareProviderRuntimeAuth: vi.fn(async () => ({ resolvedApiKey: undefined })),
    resolveProviderReasoningOutputModeWithPlugin: vi.fn(() => undefined),
    resolveProviderSystemPromptContribution: vi.fn(() => undefined),
    resolveProviderTextTransforms: vi.fn(() => undefined),
    transformProviderSystemPrompt: vi.fn(
      (params: { systemPrompt?: string }) => params.systemPrompt,
    ),
  }));

  vi.doMock("../provider-stream.js", () => ({
    registerProviderStreamForModel: registerProviderStreamForModelMock,
  }));

  vi.doMock("../../hooks/internal-hooks.js", async () => {
    const actual = await vi.importActual<typeof import("../../hooks/internal-hooks.js")>(
      "../../hooks/internal-hooks.js",
    );
    return {
      ...actual,
      triggerInternalHook,
    };
  });

  vi.doMock("@earendil-works/pi-ai/oauth", async () => {
    const actual = await vi.importActual<typeof import("@earendil-works/pi-ai/oauth")>(
      "@earendil-works/pi-ai/oauth",
    );
    return {
      ...actual,
      getOAuthApiKey: vi.fn(),
      getOAuthProviders: vi.fn(() => []),
    };
  });

  vi.doMock("@earendil-works/pi-coding-agent", () => ({
    AuthStorage: function AuthStorage() {},
    ModelRegistry: function ModelRegistry() {},
    createAgentSession: vi.fn(async () => {
      const session = {
        sessionId: "session-1",
        messages: sessionMessages.map((message) => structuredClone(message)),
        agent: {
          streamFn: vi.fn(),
          transport: "sse",
          state: {
            get messages() {
              return session.messages;
            },
            set messages(messages: unknown[]) {
              session.messages = [...messages];
            },
          },
        },
        compact: vi.fn(async () => {
          session.messages.splice(1);
          return await sessionCompactImpl();
        }),
        setActiveToolsByName: vi.fn(),
        abortCompaction: sessionAbortCompactionMock,
        dispose: vi.fn(),
      };
      return { session };
    }),
    DefaultResourceLoader: function DefaultResourceLoader() {
      return {
        reload: vi.fn(async () => undefined),
      };
    },
    SessionManager: {
      open: vi.fn(() => ({})),
    },
    SettingsManager: {
      create: vi.fn(() => ({})),
    },
    estimateTokens: estimateTokensMock,
    generateSummary: vi.fn(async () => "summary"),
  }));

  vi.doMock("../session-tool-result-guard-wrapper.js", () => ({
    guardSessionManager: guardSessionManagerMock,
  }));

  vi.doMock("../pi-settings.js", () => ({
    applyPiAutoCompactionGuard: vi.fn(() => ({ supported: true, disabled: false })),
    applyPiCompactionSettingsFromConfig: applyPiCompactionSettingsFromConfigMock,
    ensurePiCompactionReserveTokens: vi.fn(),
    isSilentOverflowProneModel: vi.fn(() => false),
    resolveCompactionReserveTokensFloor: vi.fn(() => 0),
  }));

  vi.doMock("../models-config.js", () => ({
    ensureOpenClawModelsJson: vi.fn(async () => {}),
  }));

  vi.doMock("../model-auth.js", () => ({
    applyAuthHeaderOverride: vi.fn((model: unknown) => model),
    applyLocalNoAuthHeaderOverride: vi.fn((model: unknown) => model),
    ensureAuthProfileStoreWithoutExternalProfiles: vi.fn(() => ({})),
    formatMissingAuthError: vi.fn(
      (auth: { mode: string; source: string }, provider: string) =>
        `No API key resolved for provider "${provider}" (auth mode: ${auth.mode}, checked: ${auth.source}).`,
    ),
    getApiKeyForModel: vi.fn(async () => ({
      apiKey: "test",
      mode: "env",
      source: "test harness",
    })),
    resolveModelAuthMode: vi.fn(() => "env"),
  }));

  vi.doMock("../sandbox.js", () => ({
    resolveSandboxContext: resolveSandboxContextMock,
  }));

  vi.doMock("../session-file-repair.js", () => ({
    repairSessionFileIfNeeded: vi.fn(async () => {}),
  }));

  vi.doMock("../session-write-lock.js", () => ({
    acquireSessionWriteLock: vi.fn(async () => ({ release: vi.fn(async () => {}) })),
    resolveSessionLockMaxHoldFromTimeout: vi.fn(() => 0),
    resolveSessionWriteLockAcquireTimeoutMs: vi.fn(() => 60_000),
    resolveSessionWriteLockOptions: vi.fn(() => ({
      timeoutMs: 60_000,
      staleMs: 1_800_000,
      maxHoldMs: 300_000,
    })),
  }));

  vi.doMock("../../context-engine/init.js", () => ({
    ensureContextEnginesInitialized: vi.fn(),
  }));

  vi.doMock("../../context-engine/registry.js", () => ({
    resolveContextEngine: resolveContextEngineMock,
    resolveContextEngineOwnerPluginId: vi.fn(() => "lossless-claw"),
  }));

  vi.doMock("../../process/command-queue.js", () => ({
    enqueueCommandInLane: enqueueCommandInLaneMock,
    clearCommandLane: vi.fn(() => 0),
  }));

  vi.doMock("./lanes.js", () => ({
    resolveSessionLane: vi.fn(() => "test-session-lane"),
    resolveEmbeddedSessionLane: vi.fn(() => "test-session-lane"),
    resolveGlobalLane: vi.fn(() => "test-global-lane"),
  }));

  vi.doMock("../context-window-guard.js", () => ({
    resolveContextWindowInfo: resolveContextWindowInfoMock,
  }));

  vi.doMock("../bootstrap-files.js", () => ({
    makeBootstrapWarn: vi.fn(() => () => {}),
    resolveContextInjectionMode: vi.fn(() => "always"),
    resolveBootstrapContextForRun: vi.fn(async () => ({ contextFiles: [] })),
  }));

  vi.doMock("../pi-bundle-mcp-tools.js", () => ({
    retireSessionMcpRuntime: vi.fn(async () => true),
    createBundleMcpToolRuntime: vi.fn(async () => ({
      tools: [],
      dispose: vi.fn(async () => {}),
    })),
  }));

  vi.doMock("../pi-bundle-lsp-runtime.js", () => ({
    createBundleLspToolRuntime: vi.fn(async () => ({
      tools: [],
      sessions: [],
      dispose: vi.fn(async () => {}),
    })),
  }));

  vi.doMock("../docs-path.js", () => ({
    resolveOpenClawReferencePaths: vi.fn(async () => ({
      docsPath: undefined,
      sourcePath: undefined,
    })),
  }));

  vi.doMock("../channel-tools.js", () => ({
    listChannelSupportedActions: vi.fn(() => undefined),
    resolveChannelMessageToolHints: vi.fn(() => undefined),
  }));

  vi.doMock("../pi-tools.js", () => ({
    createOpenClawCodingTools: createOpenClawCodingToolsMock,
    resolveProcessToolScopeKey: ({
      scopeKey,
      sessionKey,
      sessionId,
      agentId,
    }: {
      scopeKey?: string;
      sessionKey?: string;
      sessionId?: string;
      agentId?: string;
    }) => scopeKey ?? sessionKey ?? sessionId ?? (agentId ? `agent:${agentId}` : undefined),
  }));

  vi.doMock("./replay-history.js", () => ({
    sanitizeSessionHistory: sanitizeSessionHistoryMock,
    validateReplayTurns: vi.fn(async ({ messages }: { messages: unknown[] }) => messages),
  }));

  vi.doMock("./tool-schema-runtime.js", () => ({
    logProviderToolSchemaDiagnostics: vi.fn(),
    normalizeProviderToolSchemas: vi.fn(({ tools }: { tools: unknown[] }) => tools),
  }));

  vi.doMock("./stream-resolution.js", () => ({
    resolveEmbeddedAgentApiKey: vi.fn(async () => "test-api-key"),
    resolveEmbeddedAgentBaseStreamFn: vi.fn(() => vi.fn()),
    resolveEmbeddedAgentStreamFn: resolveEmbeddedAgentStreamFnMock,
  }));

  vi.doMock("./extra-params.js", () => ({
    applyExtraParamsToAgent: applyExtraParamsToAgentMock,
    resolveAgentTransportOverride: resolveAgentTransportOverrideMock,
    resolvePreparedExtraParams: vi.fn(() => ({})),
  }));

  vi.doMock("./tool-split.js", () => ({
    splitSdkTools: vi.fn(() => ({ customTools: [] })),
  }));

  vi.doMock("./compaction-safety-timeout.js", () => {
    const compactWithSafetyTimeout = vi.fn(
      async (
        compact: () => Promise<unknown>,
        _timeoutMs?: number,
        opts?: { abortSignal?: AbortSignal; onCancel?: () => void },
      ) => {
        const abortSignal = opts?.abortSignal;
        if (!abortSignal) {
          return await compact();
        }
        const cancelAndCreateError = () => {
          opts?.onCancel?.();
          const reason = "reason" in abortSignal ? abortSignal.reason : undefined;
          if (reason instanceof Error) {
            return reason;
          }
          const err = new Error("aborted");
          err.name = "AbortError";
          return err;
        };
        if (abortSignal.aborted) {
          throw cancelAndCreateError();
        }
        return await Promise.race([
          compact(),
          new Promise<never>((_, reject) => {
            abortSignal.addEventListener(
              "abort",
              () => {
                reject(cancelAndCreateError());
              },
              { once: true },
            );
          }),
        ]);
      },
    );
    return {
      compactWithSafetyTimeout,
      resolveCompactionTimeoutMs: vi.fn(() => 30_000),
      // Mirror the real wrapper: bound the engine's compact() with the
      // (mocked) safety timeout and thread the abort signal into its params.
      compactContextEngineWithSafetyTimeout: vi.fn(
        (
          contextEngine: { compact: (params: Record<string, unknown>) => Promise<unknown> },
          params: Record<string, unknown>,
          timeoutMs?: number,
          abortSignal?: AbortSignal,
        ) =>
          compactWithSafetyTimeout(
            () => contextEngine.compact(abortSignal ? { ...params, abortSignal } : params),
            timeoutMs,
            abortSignal ? { abortSignal } : undefined,
          ),
      ),
    };
  });

  vi.doMock("./compaction-successor-transcript.js", async () => {
    const actual = await vi.importActual<typeof import("./compaction-successor-transcript.js")>(
      "./compaction-successor-transcript.js",
    );
    return {
      ...actual,
      rotateTranscriptAfterCompaction: rotateTranscriptAfterCompactionMock,
    };
  });

  vi.doMock("./wait-for-idle-before-flush.js", () => ({
    flushPendingToolResultsAfterIdle: vi.fn(async () => {}),
  }));

  vi.doMock("../transcript-policy.js", () => ({
    resolveTranscriptPolicy: vi.fn(() => ({
      allowSyntheticToolResults: false,
      validateGeminiTurns: false,
      validateAnthropicTurns: false,
    })),
  }));

  vi.doMock("./extensions.js", () => ({
    buildEmbeddedExtensionFactories: vi.fn(() => []),
  }));

  vi.doMock("./history.js", () => ({
    getHistoryLimitFromSessionKey: vi.fn(() => undefined),
    limitHistoryTurns: vi.fn((msgs: unknown[]) => msgs.slice(0, 2)),
  }));

  vi.doMock("../skills.js", () => ({
    applySkillEnvOverrides: vi.fn(() => () => {}),
    applySkillEnvOverridesFromSnapshot: vi.fn(() => () => {}),
    loadWorkspaceSkillEntries: vi.fn(() => []),
    resolveSkillsPromptForRun: vi.fn(() => undefined),
  }));

  vi.doMock("../agent-scope.js", () => ({
    listAgentEntries: vi.fn(() => []),
    resolveAgentConfig: vi.fn(() => undefined),
    resolveAgentDir: vi.fn((_cfg: unknown, agentId: string) => `/tmp/agents/${agentId}/agent`),
    resolveDefaultAgentDir: vi.fn(() => "/tmp/agents/main/agent"),
    resolveDefaultAgentId: vi.fn(() => "main"),
    resolveRunModelFallbacksOverride: vi.fn(() => undefined),
    resolveSessionAgentId: resolveSessionAgentIdMock,
    resolveSessionAgentIds: resolveSessionAgentIdsMock,
  }));

  vi.doMock("../auth-profiles/source-check.js", () => ({
    hasAnyAuthProfileStoreSource: vi.fn(() => false),
  }));

  vi.doMock("../memory-search.js", () => ({
    resolveMemorySearchConfig: resolveMemorySearchConfigMock,
  }));

  vi.doMock("../runtime-plan/build.js", () => ({
    buildAgentRuntimePlan: vi.fn((params: BuildAgentRuntimePlanParams) =>
      createCompactHooksRuntimePlan(params),
    ),
  }));

  vi.doMock("../../plugins/memory-runtime.js", () => ({
    getActiveMemorySearchManager: getMemorySearchManagerMock,
  }));

  vi.doMock("../date-time.js", () => ({
    formatUserTime: vi.fn(() => ""),
    resolveUserTimeFormat: vi.fn(() => ""),
    resolveUserTimezone: vi.fn(() => ""),
  }));

  vi.doMock("../defaults.js", () => ({
    DEFAULT_MODEL: "fake-model",
    DEFAULT_PROVIDER: "openai",
    DEFAULT_CONTEXT_TOKENS: 128_000,
  }));

  vi.doMock("../utils.js", () => ({
    resolveUserPath: vi.fn((p: string) => p),
  }));

  vi.doMock("../../infra/machine-name.js", () => ({
    getMachineDisplayName: vi.fn(async () => "machine"),
  }));

  vi.doMock("../../config/channel-capabilities.js", () => ({
    resolveChannelCapabilities: vi.fn(() => undefined),
  }));

  vi.doMock("../../utils/message-channel.js", async () => {
    const actual = await vi.importActual<typeof import("../../utils/message-channel.js")>(
      "../../utils/message-channel.js",
    );
    return {
      ...actual,
      normalizeMessageChannel: vi.fn(() => undefined),
    };
  });

  vi.doMock("../pi-embedded-helpers.js", () => ({
    ensureSessionHeader: vi.fn(async () => {}),
    pickFallbackThinkingLevel: vi.fn((params: { message?: string; attempted?: Set<string> }) =>
      params.message?.includes("Reasoning is mandatory") && !params.attempted?.has("minimal")
        ? "minimal"
        : undefined,
    ),
    validateAnthropicTurns: vi.fn((m: unknown[]) => m),
    validateGeminiTurns: vi.fn((m: unknown[]) => m),
  }));

  vi.doMock("../pi-project-settings.js", () => ({
    createPreparedEmbeddedPiSettingsManager: createPreparedEmbeddedPiSettingsManagerMock,
  }));

  vi.doMock("./sandbox-info.js", () => ({
    buildEmbeddedSandboxInfo: vi.fn(() => undefined),
  }));

  vi.doMock("./model.js", () => ({
    buildModelAliasLines: vi.fn(() => []),
    resolveModel: resolveModelMock,
    resolveModelAsync: vi.fn(
      async (provider: string, modelId: string, agentDir?: string, cfg?: unknown) =>
        resolveModelMock(provider, modelId, agentDir, cfg),
    ),
  }));

  vi.doMock("./session-manager-cache.js", () => ({
    prewarmSessionFile: vi.fn(async () => {}),
    trackSessionManagerAccess: vi.fn(),
  }));

  vi.doMock("./system-prompt.js", () => ({
    applySystemPromptOverrideToSession: vi.fn(),
    buildEmbeddedSystemPrompt: buildEmbeddedSystemPromptMock,
    createSystemPromptOverride: vi.fn(() => () => ""),
  }));

  vi.doMock("./utils.js", async () => {
    const actual = await vi.importActual<typeof import("./utils.js")>("./utils.js");
    return {
      ...actual,
      describeUnknownError: vi.fn((err: unknown) => String(err)),
      mapThinkingLevel: vi.fn((level?: string) => level ?? "off"),
      resolveExecToolDefaults: vi.fn(() => undefined),
    };
  });

  const [compactModule, compactQueuedModule, transcriptEvents] = await Promise.all([
    import("./compact.js"),
    import("./compact.queued.js"),
    import("../../sessions/transcript-events.js"),
  ]);

  return {
    ...compactModule,
    compactEmbeddedPiSession: compactQueuedModule.compactEmbeddedPiSession,
    onSessionTranscriptUpdate: transcriptEvents.onSessionTranscriptUpdate,
  };
}
