import { ProviderHealthManager } from './health-manager.js';
import { ProviderRegistry } from './provider-registry.js';
import { RouteLoadBalancer } from './load-balancer.js';
import { RoutingClassifier } from './classifier.js';
import { ContextAdvisor } from './context-advisor.js';
import { getStatsCenter } from '../../telemetry/stats-center.js';
import { loadRoutingInstructionStateSync, saveRoutingInstructionStateAsync, saveRoutingInstructionStateSync } from './sticky-session-store.js';
import { resolveStickyKey as resolveStickyKeyImpl, resolveSessionScope as resolveSessionScopeImpl } from './engine/routing-state/keys.js';
import { RouteAnalytics } from './engine/route-analytics.js';
import { StickySessionManager } from './engine/sticky-session-manager.js';
import { CooldownManager } from './engine/cooldown-manager.js';
import { VirtualRouterEngine as NativeVirtualRouterEngine } from './engine.js';
import { updateDeps as updateDepsImpl, initialize as initializeImpl } from './engine-legacy/config.js';
import { handleProviderError as handleProviderErrorImpl, handleProviderFailure as handleProviderFailureImpl, handleProviderSuccess as handleProviderSuccessImpl, buildHealthSnapshot as buildHealthSnapshotImpl, persistHealthSnapshot as persistHealthSnapshotImpl, markProviderCooldown as markProviderCooldownImpl, clearProviderCooldown as clearProviderCooldownImpl, isProviderCoolingDown as isProviderCoolingDownImpl, getProviderCooldownRemainingMs as getProviderCooldownRemainingMsImpl, restoreHealthFromStore as restoreHealthFromStoreImpl } from './engine-legacy/health.js';
import { selectProvider as selectProviderImpl, selectFromCandidates as selectFromCandidatesImpl, selectFromStickyPool as selectFromStickyPoolImpl, extractExcludedProviderKeySet as extractExcludedProviderKeySetImpl } from './engine-legacy/selection-core.js';
import { parseDirectProviderModel as parseDirectProviderModelImpl, shouldFallbackDirectModelForMedia as shouldFallbackDirectModelForMediaImpl } from './engine-legacy/direct-model.js';
import { normalizeRouteAlias as normalizeRouteAliasImpl, buildRouteCandidates as buildRouteCandidatesImpl, reorderForInlineVision as reorderForInlineVisionImpl, reorderForPreferredModel as reorderForPreferredModelImpl, routeSupportsModel as routeSupportsModelImpl, routeSupportsInlineVision as routeSupportsInlineVisionImpl, sortByPriority as sortByPriorityImpl, routeWeight as routeWeightImpl, routeHasForceFlag as routeHasForceFlagImpl, routeHasTargets as routeHasTargetsImpl, hasPrimaryPool as hasPrimaryPoolImpl, sortRoutePools as sortRoutePoolsImpl, flattenPoolTargets as flattenPoolTargetsImpl } from './engine-legacy/route-utils.js';
import { resolveSelectionPenalty as resolveSelectionPenaltyImpl, resolveInstructionProcessModeForSelection as resolveInstructionProcessModeForSelectionImpl, resolveInstructionTarget as resolveInstructionTargetImpl, filterCandidatesByRoutingState as filterCandidatesByRoutingStateImpl, buildStickyRouteCandidatesFromFiltered as buildStickyRouteCandidatesFromFilteredImpl } from './engine-legacy/selection-state.js';
const ALLOW_ENGINE_LEGACY_IMPORTS = process.env.LLMSWITCH_ALLOW_ENGINE_LEGACY_IMPORTS === '1' ||
    process.env.ROUTECODEX_ALLOW_ENGINE_LEGACY_IMPORTS === '1';
if (!ALLOW_ENGINE_LEGACY_IMPORTS) {
    throw new Error('[engine-legacy] import is fail-closed. Set LLMSWITCH_ALLOW_ENGINE_LEGACY_IMPORTS=1 only for explicit compatibility/debug work.');
}
function warnLegacyCompatibilitySurface(method) {
    const enabled = process.env.LLMSWITCH_WARN_LEGACY_SURFACES === '1' ||
        process.env.ROUTECODEX_WARN_LEGACY_SURFACES === '1';
    if (!enabled) {
        return;
    }
    try {
        // eslint-disable-next-line no-console
        console.warn(`[engine-legacy] compatibility surface invoked: ${method}. Do not add new runtime logic to engine-legacy helpers.`);
    }
    catch {
        // best-effort only
    }
}
export class VirtualRouterEngine {
    routing = {};
    providerRegistry = new ProviderRegistry();
    healthManager = new ProviderHealthManager();
    loadBalancer = new RouteLoadBalancer();
    classifier = new RoutingClassifier({});
    contextAdvisor = new ContextAdvisor();
    contextRouting;
    routeAnalytics = new RouteAnalytics();
    stickySessionManager = new StickySessionManager();
    cooldownManager;
    antigravityLeasePersistence = { loadedOnce: false, loadedMtimeMs: null, flushTimer: null };
    debug = console; // thin hook; host may monkey-patch for colored logging
    healthConfig = null;
    statsCenter = getStatsCenter();
    // Derived flags from VirtualRouterConfig/routing used by process / response layers.
    webSearchForce = false;
    healthStore;
    routingStateStore = {
        loadSync: loadRoutingInstructionStateSync,
        saveAsync: saveRoutingInstructionStateAsync,
        saveSync: saveRoutingInstructionStateSync
    };
    routingInstructionState = new Map();
    quotaView;
    nativeEngine;
    /**
     * Backward-compatible test/debug surface used by existing regression scripts.
     * Keep this as a read-only view over StickySessionManager storage.
     */
    get antigravitySessionAliasStore() {
        return this.nativeEngine.antigravitySessionAliasStore;
    }
    constructor(deps) {
        this.nativeEngine = new NativeVirtualRouterEngine(deps);
        this.cooldownManager = new CooldownManager({
            healthStore: deps?.healthStore,
            healthConfig: this.healthConfig,
            quotaView: deps?.quotaView
        });
        if (deps?.healthStore) {
            this.healthStore = deps.healthStore;
        }
        if (deps?.routingStateStore) {
            this.routingStateStore = deps.routingStateStore;
        }
        if (deps?.quotaView) {
            this.quotaView = deps.quotaView;
        }
    }
    updateDeps(deps) {
        updateDepsImpl(this, deps);
        this.nativeEngine.updateDeps(deps);
    }
    initialize(config) {
        initializeImpl(this, config);
        this.nativeEngine.initialize(config);
    }
    route(request, metadata) {
        return this.nativeEngine.route(request, metadata);
    }
    getStopMessageState(metadata) {
        return this.nativeEngine.getStopMessageState(metadata);
    }
    getPreCommandState(metadata) {
        return this.nativeEngine.getPreCommandState(metadata);
    }
    handleProviderFailure(event) {
        handleProviderFailureImpl(this, event);
        this.nativeEngine.handleProviderFailure(event);
    }
    handleProviderError(event) {
        handleProviderErrorImpl(this, event);
        this.nativeEngine.handleProviderError(event);
    }
    handleProviderSuccess(event) {
        handleProviderSuccessImpl(this, event);
        this.nativeEngine.handleProviderSuccess(event);
    }
    getStatus() {
        return this.nativeEngine.getStatus();
    }
    normalizeRouteAlias(routeName) {
        warnLegacyCompatibilitySurface('normalizeRouteAlias');
        return normalizeRouteAliasImpl(routeName);
    }
    buildRouteCandidates(requestedRoute, classificationCandidates, features) {
        warnLegacyCompatibilitySurface('buildRouteCandidates');
        return buildRouteCandidatesImpl(this, requestedRoute, classificationCandidates, features);
    }
    reorderForInlineVision(routeNames) {
        warnLegacyCompatibilitySurface('reorderForInlineVision');
        return reorderForInlineVisionImpl(this, routeNames);
    }
    reorderForPreferredModel(routeNames, modelId) {
        warnLegacyCompatibilitySurface('reorderForPreferredModel');
        return reorderForPreferredModelImpl(this, routeNames, modelId);
    }
    routeSupportsModel(routeName, modelId) {
        warnLegacyCompatibilitySurface('routeSupportsModel');
        return routeSupportsModelImpl(this, routeName, modelId);
    }
    routeSupportsInlineVision(routeName) {
        warnLegacyCompatibilitySurface('routeSupportsInlineVision');
        return routeSupportsInlineVisionImpl(this, routeName);
    }
    sortByPriority(routeNames) {
        warnLegacyCompatibilitySurface('sortByPriority');
        return sortByPriorityImpl(routeNames);
    }
    routeWeight(routeName) {
        warnLegacyCompatibilitySurface('routeWeight');
        return routeWeightImpl(routeName);
    }
    routeHasForceFlag(routeName) {
        warnLegacyCompatibilitySurface('routeHasForceFlag');
        return routeHasForceFlagImpl(this, routeName);
    }
    routeHasTargets(pools) {
        warnLegacyCompatibilitySurface('routeHasTargets');
        return routeHasTargetsImpl(this, pools);
    }
    hasPrimaryPool(pools) {
        warnLegacyCompatibilitySurface('hasPrimaryPool');
        return hasPrimaryPoolImpl(this, pools);
    }
    sortRoutePools(pools) {
        warnLegacyCompatibilitySurface('sortRoutePools');
        return sortRoutePoolsImpl(this, pools);
    }
    flattenPoolTargets(pools) {
        warnLegacyCompatibilitySurface('flattenPoolTargets');
        return flattenPoolTargetsImpl(this, pools);
    }
    markProviderCooldown(providerKey, cooldownMs) {
        markProviderCooldownImpl(this, providerKey, cooldownMs);
        this.nativeEngine.markProviderCooldown(providerKey, cooldownMs);
    }
    clearProviderCooldown(providerKey) {
        clearProviderCooldownImpl(this, providerKey);
        this.nativeEngine.clearProviderCooldown(providerKey);
    }
    isProviderCoolingDown(providerKey) {
        return isProviderCoolingDownImpl(this, providerKey);
    }
    getProviderCooldownRemainingMs(providerKey) {
        return getProviderCooldownRemainingMsImpl(this, providerKey);
    }
    restoreHealthFromStore() {
        restoreHealthFromStoreImpl(this);
    }
    buildHealthSnapshot() {
        return buildHealthSnapshotImpl(this);
    }
    persistHealthSnapshot() {
        persistHealthSnapshotImpl(this);
    }
    parseDirectProviderModel(model) {
        return parseDirectProviderModelImpl(this, model);
    }
    shouldFallbackDirectModelForMedia(direct, features) {
        return shouldFallbackDirectModelForMediaImpl(this, direct, features);
    }
    selectProvider(requestedRoute, metadata, classification, features, routingState) {
        warnLegacyCompatibilitySurface('selectProvider');
        return selectProviderImpl(this, requestedRoute, metadata, classification, features, routingState);
    }
    selectFromCandidates(routes, metadata, classification, features, state, requiredProviderKeys, allowAliasRotation) {
        warnLegacyCompatibilitySurface('selectFromCandidates');
        return selectFromCandidatesImpl(this, routes, metadata, classification, features, state, requiredProviderKeys, allowAliasRotation);
    }
    selectFromStickyPool(stickyKeySet, metadata, features, state, allowAliasRotation) {
        warnLegacyCompatibilitySurface('selectFromStickyPool');
        return selectFromStickyPoolImpl(this, stickyKeySet, metadata, features, state, allowAliasRotation);
    }
    extractExcludedProviderKeySet(metadata) {
        warnLegacyCompatibilitySurface('extractExcludedProviderKeySet');
        return extractExcludedProviderKeySetImpl(this, metadata);
    }
    resolveSelectionPenalty(providerKey) {
        warnLegacyCompatibilitySurface('resolveSelectionPenalty');
        return resolveSelectionPenaltyImpl(this, providerKey);
    }
    resolveInstructionProcessModeForSelection(providerKey, routingState) {
        warnLegacyCompatibilitySurface('resolveInstructionProcessModeForSelection');
        return resolveInstructionProcessModeForSelectionImpl(this, providerKey, routingState);
    }
    resolveInstructionTarget(target) {
        warnLegacyCompatibilitySurface('resolveInstructionTarget');
        return resolveInstructionTargetImpl(this, target);
    }
    buildStickyRouteCandidatesFromFiltered(filteredCandidates, stickyKeySet) {
        warnLegacyCompatibilitySurface('buildStickyRouteCandidatesFromFiltered');
        return buildStickyRouteCandidatesFromFilteredImpl(this, filteredCandidates, stickyKeySet);
    }
    filterCandidatesByRoutingState(routes, state) {
        warnLegacyCompatibilitySurface('filterCandidatesByRoutingState');
        return filterCandidatesByRoutingStateImpl(this, routes, state);
    }
    resolveStickyKey(metadata) {
        warnLegacyCompatibilitySurface('resolveStickyKey');
        return resolveStickyKeyImpl(metadata);
    }
    resolveSessionScope(metadata) {
        warnLegacyCompatibilitySurface('resolveSessionScope');
        return resolveSessionScopeImpl(metadata);
    }
}
