import { Request, Router } from 'express';
import { IncomingMessage } from 'http';
import { Duplex } from 'stream';
import { DebuggerManager } from './debugger-manager.js';

/**
 * Multi-session debugger HTTP + WS routes — shared between the CLI
 * (`shiplight debug`), the testbox OmniTerm server, and future consumers
 * like the VSCode extension.
 *
 * All three hosts mount the same routes and the same URL scheme:
 *
 *   POST   /api/debugger/sessions          — open a session for a yaml path
 *   GET    /api/debugger/sessions          — list live sessions
 *   DELETE /api/debugger/sessions/:id      — close a session
 *   GET    /debugger/static/*              — debugger SPA bundle
 *   GET    /debugger/:sessionId/           — HTML shell for the iframe
 *   ANY    /debugger/:sessionId/*          — HTTP reverse proxy to the inner
 *   (upgrade) /ws/debugger/:sessionId/*    — WebSocket proxy (via handleDebuggerUpgrade)
 *
 * The shared module is host-agnostic; each consumer supplies:
 *  - the `DebuggerManager` instance (shared so all sessions live in one map)
 *  - the static asset directory (where the built debugger SPA lives)
 *  - an optional `resolveYamlPath` gate (the testbox uses confinePath; the
 *    CLI has no trusted root so it accepts any reachable yaml)
 *
 * See specs/004-testbox-debugger/contracts/{session-api,proxy-routes,embedded-ui}.md
 */

interface ServerRoutesOptions {
    /** The shared multi-session manager. One instance per host process. */
    manager: DebuggerManager;
    /**
     * Absolute path to the directory serving the built debugger SPA (contains
     * `index.html` + `assets/`). The testbox stages this from the CLI's build
     * output; the CLI points directly at its own `dist/static`.
     */
    staticDir: string;
    /**
     * Optional gate on the incoming yamlPath. Return the absolute path to
     * allow, or `null` to refuse with 403. Defaults to pass-through absolute
     * resolution — suitable for the CLI, where path confinement is the OS's
     * job. The testbox supplies `confinePath(raw, allowedRoots())`.
     */
    resolveYamlPath?: (raw: string) => string | null;
    /**
     * Optional override for the liveview-url builder. Receives the session-id
     * from the URL + the incoming request; returns the ws:// URL the SPA
     * should connect to for the live CDP DevTools view. Defaults to
     * `ws://host/ws/debugger/:sessionId/cdp-browser`.
     */
    liveviewUrlBuilder?: (sessionId: string, req: Request) => string;
    /**
     * Fallback router for idle sessions (no sandbox process). When the SPA
     * makes file-related API calls (`/api/test-flow`, `/api/files`, etc.)
     * through the session proxy but the sandbox isn't running, the proxy
     * delegates to this router instead of forwarding to the inner process.
     */
    fallbackRouter?: Router;
    /**
     * Absolute path to the artifacts directory (screenshots, videos).
     * When set, `/api/report-assets/*` requests inside a session are served
     * from this directory instead of being proxied to the inner process.
     */
    artifactsDir?: string;
}
declare function createDebuggerHttpRoutes(opts: ServerRoutesOptions): Router;
/**
 * WebSocket upgrade dispatcher for `/ws/debugger/:sessionId/<inner-path>`.
 * Call from your HTTP server's `upgrade` listener when the URL matches:
 *
 *   if (url.startsWith("/ws/debugger/")) {
 *     handleDebuggerUpgrade(manager, req, socket, head);
 *     return;
 *   }
 */
declare function handleDebuggerUpgrade(manager: DebuggerManager, req: IncomingMessage, socket: Duplex, head: Buffer): void;

export { type ServerRoutesOptions, createDebuggerHttpRoutes, handleDebuggerUpgrade };
