import { type TlsFetchResult } from './tls-tier.js';
import type { RawFetchResult, BrowserAction, Mode, StageError } from '../types.js';
export interface RouterFetchOptions {
    renderJs?: 'auto' | 'always' | 'never';
    useAuth?: boolean;
    headers?: Record<string, string>;
    screenshot?: boolean;
    actions?: BrowserAction[];
    force_refresh?: boolean;
    mode?: Mode;
    /**
     * Conditional-GET headers. When set, the HTTP path sends them with the
     * request and a 304 response is returned as RawFetchResult with
     * statusCode=304 + html=''. Routes that always escalate to Playwright
     * (renderJs=always, useAuth, actions) ignore these headers.
     */
    conditionalHeaders?: {
        ifNoneMatch?: string;
        ifModifiedSince?: string;
    };
}
export interface HttpClient {
    fetch(url: string, options?: {
        headers?: Record<string, string>;
        timeoutMs?: number;
        conditionalHeaders?: {
            ifNoneMatch?: string;
            ifModifiedSince?: string;
        };
    }): Promise<{
        url: string;
        finalUrl: string;
        html: string;
        contentType: string;
        statusCode: number;
        headers: Record<string, string>;
        rawBuffer?: Buffer;
    }>;
}
export interface BrowserPoolInterface {
    fetchWithBrowser(url: string, options?: {
        headers?: Record<string, string>;
        storageStatePath?: string;
        userDataDir?: string;
        screenshot?: boolean;
        actions?: BrowserAction[];
        cdpUrl?: string;
    }): Promise<RawFetchResult>;
}
export type HttpFetcher = (url: string, options?: {
    headers?: Record<string, string>;
    timeoutMs?: number;
}) => Promise<{
    url: string;
    html: string;
    text: string;
}>;
export type PlaywrightFetcher = (url: string, options?: {
    timeoutMs?: number;
}) => Promise<{
    html: string;
    text: string;
}>;
/**
 * Slice D2: injectable TLS-impersonation fetcher. Same shape as `tlsFetch`
 * from tls-tier.ts; left injectable so unit tests can stub without touching
 * the wreq-js native binary.
 */
export type TlsFetcher = (url: string, options?: {
    headers?: Record<string, string>;
    timeoutMs?: number;
}) => Promise<TlsFetchResult>;
/** Pluggable hooks to learning/persistence layer so router tests don't need a DB. */
export interface TlsRoutingPersistence {
    getPreferTls(domain: string): boolean;
    recordSuccess(domain: string): void;
}
export interface SmartRouterOptions {
    httpClient?: HttpClient;
    browserPool?: BrowserPoolInterface;
    httpFetcher?: HttpFetcher;
    playwrightFetcher?: PlaywrightFetcher;
    /** Slice D2 — when provided, overrides the default lazy-loaded wreq backend. */
    tlsFetcher?: TlsFetcher;
    /** Slice D2 — persistence for `prefer_tls_impersonation` learning. */
    tlsPersistence?: TlsRoutingPersistence;
}
interface DomainStats {
    failureCount: number;
    preferPlaywright: boolean;
}
export declare class SmartRouter {
    private readonly domainMap;
    private readonly httpClient?;
    private readonly browserPool?;
    private readonly httpFetcher;
    private readonly playwrightFetcher;
    private readonly tlsFetcher;
    private readonly tlsPersistence;
    constructor(httpClient: HttpClient, browserPool: BrowserPoolInterface);
    constructor(options: SmartRouterOptions);
    private makeDefaultHttpFetcher;
    fetch(url: string, options: RouterFetchOptions & {
        mode: 'stealth';
    }): Promise<RawFetchResult | StageError>;
    fetch(url: string, options?: RouterFetchOptions): Promise<RawFetchResult>;
    getDomainStats(domain: string): DomainStats | undefined;
    private ensureStats;
    static isKnownSpaDomain(host: string): boolean;
    private toRawFetchResult;
    /**
     * Attempt the TLS-impersonation tier for `url`. Returns:
     *  - { ok: true, result } when the tier completed AND the response does
     *    not look like a still-blocking challenge / JS-required page
     *  - { ok: false, reason } when the tier is unavailable (missing native
     *    binary, network error) OR the response still looks anti-bot / JS-
     *    required so the router should escalate to Playwright.
     *
     * Records success against the domain on every healthy response. The
     * `prefer_tls_impersonation` flip is performed by the persistence layer
     * once the success threshold is reached.
     */
    private tryTlsTier;
}
export {};
//# sourceMappingURL=router.d.ts.map