import { join } from 'node:path';
import { ConfigManager } from '../config/manager.js';
import { SecretsManager } from '../config/secrets.js';
import { ServiceRegistry } from '../config/service-registry.js';
import { SubscriptionManager } from '@pellux/goodvibes-sdk/platform/config/subscriptions';
import { AutomationDeliveryManager, AutomationManager, AutomationRouteStore } from '../automation/index.js';
import { ChannelPluginRegistry, ChannelPolicyManager, RouteBindingManager, SurfaceRegistry } from '../channels/index.js';
import { ChannelDeliveryRouter } from '../channels/delivery-router.js';
import { ApprovalBroker, GatewayMethodCatalog, SharedSessionBroker } from '../control-plane/index.js';
import { WatcherRegistry } from '../watchers/index.js';
import { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts/index';
import { KnowledgeService, KnowledgeStore } from '../knowledge/index.js';
import { MediaProviderRegistry, ensureBuiltinMediaProviders } from '../media/index.js';
import { MultimodalService } from '../multimodal/index.js';
import { AgentManager } from '../tools/agent/index.js';
import { AgentMessageBus } from '../agents/message-bus.js';
import { WrfcController } from '../agents/wrfc-controller.js';
import { AgentOrchestrator } from '../agents/orchestrator.js';
import { ArchetypeLoader } from '@pellux/goodvibes-sdk/platform/agents/archetypes';
import { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools/shared/process-manager';
import { ModeManager } from '@pellux/goodvibes-sdk/platform/state/mode-manager';
import { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state/file-undo';
import { MemoryRegistry } from '../state/memory-registry.js';
import { MemoryStore } from '../state/memory-store.js';
import { createDomainDispatch } from './store/index.js';
import { DistributedRuntimeManager } from '@pellux/goodvibes-sdk/platform/runtime/remote/distributed-runtime-manager';
import { RemoteRunnerRegistry, RemoteSupervisor } from './remote/index.js';
import { IntegrationHelperService } from './integration/helpers.js';
import { VoiceProviderRegistry, VoiceService, ensureBuiltinVoiceProviders } from '@pellux/goodvibes-sdk/platform/voice/index';
import { WebSearchProviderRegistry, WebSearchService } from '../web-search/index.js';
import { MemoryEmbeddingProviderRegistry } from '../state/memory-embeddings.js';
import { HookActivityTracker } from '@pellux/goodvibes-sdk/platform/hooks/activity';
import { HookDispatcher, createHookWorkbench } from '../hooks/index.js';
import { PluginManager } from '../plugins/manager.js';
import { BookmarkManager } from '@pellux/goodvibes-sdk/platform/bookmarks/manager';
import { ProfileManager } from '@pellux/goodvibes-sdk/platform/profiles/manager';
import { SessionManager } from '../sessions/manager.js';
import { CrossSessionTaskRegistry } from '@pellux/goodvibes-sdk/platform/sessions/orchestration/index';
import { ApiTokenAuditor } from '@pellux/goodvibes-sdk/platform/security/token-audit';
import { UserAuthManager } from '@pellux/goodvibes-sdk/platform/security/user-auth';
import { WebhookNotifier } from '../integrations/webhooks.js';
import { McpRegistry } from '../mcp/registry.js';
import { DeterministicReplayEngine } from '@pellux/goodvibes-sdk/platform/core/deterministic-replay';
import { ProviderOptimizer } from '../providers/optimizer.js';
import { ProviderRegistry } from '../providers/registry.js';
import { ProviderCapabilityRegistry } from '../providers/capabilities.js';
import { CacheHitTracker } from '@pellux/goodvibes-sdk/platform/providers/cache-strategy';
import { FavoritesStore } from '@pellux/goodvibes-sdk/platform/providers/favorites';
import { BenchmarkStore } from '@pellux/goodvibes-sdk/platform/providers/model-benchmarks';
import { ModelLimitsService } from '../providers/model-limits.js';
import { SessionMemoryStore } from '@pellux/goodvibes-sdk/platform/core/session-memory';
import { SessionLineageTracker } from '@pellux/goodvibes-sdk/platform/core/session-lineage';
import { SessionChangeTracker } from '@pellux/goodvibes-sdk/platform/sessions/change-tracker';
import { ExecutionPlanManager } from '@pellux/goodvibes-sdk/platform/core/execution-plan';
import { AdaptivePlanner } from '@pellux/goodvibes-sdk/platform/core/adaptive-planner';
import { FileStateCache } from '@pellux/goodvibes-sdk/platform/state/file-cache';
import { ProjectIndex } from '@pellux/goodvibes-sdk/platform/state/project-index';
import { IdempotencyStore } from '@pellux/goodvibes-sdk/platform/runtime/idempotency/index';
import { OverflowHandler } from '@pellux/goodvibes-sdk/platform/tools/shared/overflow';
import { ToolLLM } from '../config/tool-llm.js';
import { ComponentHealthMonitor } from '@pellux/goodvibes-sdk/platform/runtime/perf/component-health-monitor';
import { WorktreeRegistry } from './worktree/registry.js';
import { SandboxSessionRegistry } from './sandbox/session-registry.js';
import { createShellPathService } from '@pellux/goodvibes-sdk/platform/runtime/shell-paths';
import { createFeatureFlagManager } from '@pellux/goodvibes-sdk/platform/runtime/feature-flags/index';
import { PolicyRuntimeState } from './permissions/policy-runtime.js';
import { requireSurfaceRoot } from './surface-root.js';
import { createNoopKeybindingsManager, createNoopPanelManager, } from './host-ui.js';
import { createWorkflowServices, } from '@pellux/goodvibes-sdk/platform/tools/workflow/index';
export function createRuntimeServices(options) {
    const workingDirectory = options.workingDir;
    const homeDirectory = options.homeDirectory;
    const surfaceRoot = requireSurfaceRoot(options.surfaceRoot, 'RuntimeServicesOptions surfaceRoot');
    const shellPaths = createShellPathService({
        workingDirectory,
        homeDirectory,
    });
    const configManager = options.configManager;
    const featureFlags = options.featureFlags ?? createFeatureFlagManager();
    const runtimeDispatch = createDomainDispatch(options.runtimeStore);
    const gatewayMethods = new GatewayMethodCatalog();
    const panelManager = options.panelManager ?? createNoopPanelManager();
    const keybindingsManager = options.keybindingsManager ?? createNoopKeybindingsManager();
    const routeBindings = new RouteBindingManager({
        store: new AutomationRouteStore({ configManager }),
        runtimeStore: options.runtimeStore,
        runtimeBus: options.runtimeBus,
    });
    const surfaceRegistry = new SurfaceRegistry(configManager, options.runtimeStore);
    const channelPlugins = new ChannelPluginRegistry();
    surfaceRegistry.attachPluginRegistry(channelPlugins);
    const secretsManager = new SecretsManager({
        projectRoot: workingDirectory,
        globalHome: homeDirectory,
        surfaceRoot,
        configManager,
    });
    const subscriptionManager = new SubscriptionManager(shellPaths.resolveUserPath(surfaceRoot, 'subscriptions.json'));
    const serviceRegistry = new ServiceRegistry(shellPaths.resolveProjectPath(surfaceRoot, 'services.json'), {
        secretsManager,
        subscriptionManager,
    });
    const providerCapabilityRegistry = new ProviderCapabilityRegistry();
    const cacheHitTracker = new CacheHitTracker();
    const favoritesStore = new FavoritesStore({ dir: shellPaths.resolveUserPath(surfaceRoot) });
    const benchmarkStore = new BenchmarkStore({ dir: shellPaths.resolveUserPath(surfaceRoot) });
    const modelLimitsService = new ModelLimitsService({
        cachePath: shellPaths.resolveUserPath(surfaceRoot, 'model-limits.json'),
    });
    const providerRegistry = new ProviderRegistry({
        configManager,
        subscriptionManager,
        secretsManager,
        serviceRegistry,
        capabilityRegistry: providerCapabilityRegistry,
        cacheHitTracker,
        favoritesStore,
        benchmarkStore,
        modelLimitsService,
        featureFlags,
        runtimeBus: options.runtimeBus,
    });
    providerRegistry.initCustomProviders();
    const toolLLM = new ToolLLM({
        configManager,
        providerRegistry,
    });
    const localUserAuthManager = new UserAuthManager({
        bootstrapFilePath: shellPaths.resolveUserPath(surfaceRoot, 'auth-users.json'),
        bootstrapCredentialPath: shellPaths.resolveUserPath(surfaceRoot, 'auth-bootstrap.txt'),
    });
    const profileManager = new ProfileManager(shellPaths.resolveUserPath(surfaceRoot, 'profiles'));
    const bookmarkManager = new BookmarkManager(shellPaths.resolveUserPath(surfaceRoot, 'bookmarks'));
    const sessionManager = new SessionManager(workingDirectory, { surfaceRoot });
    const sessionOrchestration = new CrossSessionTaskRegistry(shellPaths.resolveProjectPath(surfaceRoot, 'sessions', 'task-graph.json'));
    const hookActivityTracker = new HookActivityTracker();
    const watcherRegistry = new WatcherRegistry({
        storePath: shellPaths.resolveProjectPath(surfaceRoot, 'watchers.json'),
    });
    watcherRegistry.attachRuntime({
        runtimeStore: options.runtimeStore,
        runtimeBus: options.runtimeBus,
    });
    const agentMessageBus = new AgentMessageBus();
    agentMessageBus.setRuntimeBus(options.runtimeBus);
    const archetypeLoader = new ArchetypeLoader(join(workingDirectory, '.goodvibes', 'agents'));
    const agentOrchestrator = new AgentOrchestrator({
        messageBus: agentMessageBus,
    });
    agentOrchestrator.setRuntimeBus(options.runtimeBus);
    const agentManager = new AgentManager({
        archetypeLoader,
        messageBus: agentMessageBus,
        executor: agentOrchestrator,
        configManager,
    });
    agentManager.setRuntimeBus(options.runtimeBus);
    const wrfcController = new WrfcController(options.runtimeBus, agentMessageBus, {
        agentManager,
        configManager,
        projectRoot: workingDirectory,
        surfaceRoot,
    });
    agentManager.setWrfcController(wrfcController);
    const hookDispatcher = new HookDispatcher({ agentManager, toolLLM, projectRoot: workingDirectory }, hookActivityTracker);
    configManager.attachHookDispatcher(hookDispatcher);
    const hookWorkbench = createHookWorkbench({
        hookDispatcher,
        configManager,
    });
    const approvalBroker = new ApprovalBroker({
        storePath: shellPaths.resolveProjectPath(surfaceRoot, 'control-plane', 'approvals.json'),
    });
    const sessionBroker = new SharedSessionBroker({
        storePath: shellPaths.resolveProjectPath(surfaceRoot, 'control-plane', 'sessions.json'),
        routeBindings,
        agentStatusProvider: agentManager,
        messageSender: agentMessageBus,
    });
    sessionBroker.setContinuationRunner(async ({ task, input }) => {
        const record = agentManager.spawn({
            mode: 'spawn',
            task,
            ...(input.routing?.modelId ? { model: input.routing.modelId } : {}),
            ...(input.routing?.providerId ? { provider: input.routing.providerId } : {}),
            ...(input.routing?.tools?.length ? { tools: [...input.routing.tools], restrictTools: true } : {}),
            ...(input.routing
                ? {
                    routing: {
                        providerSelection: input.routing.providerSelection ?? (input.routing.providerId ? 'concrete' : 'inherit-current'),
                        unresolvedModelPolicy: input.routing.unresolvedModelPolicy ?? 'fallback-to-current',
                        providerFailurePolicy: input.routing.providerFailurePolicy ?? 'ordered-fallbacks',
                        ...(input.routing.fallbackModels?.length ? { fallbackModels: [...input.routing.fallbackModels] } : {}),
                    },
                }
                : {}),
            ...(input.routing?.reasoningEffort ? { reasoningEffort: input.routing.reasoningEffort } : {}),
            context: `shared-session:${input.sessionId}`,
        });
        return { agentId: record.id };
    });
    const artifactStore = new ArtifactStore({ configManager });
    const memoryEmbeddingRegistry = new MemoryEmbeddingProviderRegistry({ configManager });
    const memoryDbPath = join(workingDirectory, '.goodvibes', surfaceRoot, 'memory.sqlite');
    const memoryStore = new MemoryStore(memoryDbPath, {
        embeddingRegistry: memoryEmbeddingRegistry,
    });
    const memoryRegistry = new MemoryRegistry(memoryStore);
    const deliveryManager = new AutomationDeliveryManager({
        configManager,
        serviceRegistry,
        runtimeBus: options.runtimeBus,
        runtimeStore: options.runtimeStore,
        routeBindings,
        artifactStore,
    });
    const automationManager = new AutomationManager({
        configManager,
        routeBindings,
        sessionBroker,
        defaultSurfaceKind: surfaceRoot,
        defaultSurfaceId: `surface:${surfaceRoot}`,
        runtimeStore: options.runtimeStore,
        runtimeBus: options.runtimeBus,
        deliveryManager,
        spawnTask: (input) => {
            const record = agentManager.spawn({
                mode: 'spawn',
                task: input.prompt,
                ...(input.modelId ? { model: input.modelId } : {}),
                ...(input.modelProvider ? { provider: input.modelProvider } : {}),
                ...(input.fallbackModels !== undefined ? { fallbackModels: [...input.fallbackModels] } : {}),
                ...(input.routing ? { routing: input.routing } : {}),
                ...(input.executionIntent ? { executionIntent: input.executionIntent } : {}),
                ...(input.template ? { template: input.template } : {}),
                ...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),
                ...(input.toolAllowlist?.length ? { tools: [...input.toolAllowlist], restrictTools: true } : {}),
                ...(input.context ? { context: input.context } : {}),
            });
            return record.id;
        },
    });
    const knowledgeStore = new KnowledgeStore({ configManager });
    const knowledgeService = new KnowledgeService(knowledgeStore, artifactStore, undefined, {
        memoryRegistry,
        runtimeBus: options.runtimeBus,
    });
    knowledgeService.attachRuntimeBus(options.runtimeBus);
    const voiceProviders = new VoiceProviderRegistry();
    ensureBuiltinVoiceProviders(voiceProviders);
    const voiceService = new VoiceService(voiceProviders);
    const webSearchProviders = new WebSearchProviderRegistry({
        env: process.env,
        serviceRegistry,
    });
    const webSearchService = new WebSearchService(webSearchProviders, {
        serviceRegistry,
        featureFlags,
    });
    const mediaProviders = new MediaProviderRegistry();
    ensureBuiltinMediaProviders(mediaProviders, artifactStore, providerRegistry);
    const multimodalService = new MultimodalService(artifactStore, mediaProviders, voiceService, knowledgeService);
    const pluginManager = new PluginManager({
        pathOptions: {
            cwd: shellPaths.workingDirectory,
            homeDir: shellPaths.homeDirectory,
        },
        stateFilePath: shellPaths.resolveUserPath(surfaceRoot, 'plugins.json'),
    });
    const workflow = createWorkflowServices();
    hookDispatcher.setTriggerManager(workflow.triggerManager);
    const channelPolicy = new ChannelPolicyManager({
        storePath: shellPaths.resolveProjectPath(surfaceRoot, 'channels', 'policies.json'),
    });
    const distributedRuntime = new DistributedRuntimeManager(shellPaths.resolveProjectPath(surfaceRoot, 'remote', 'distributed-runtime.json'));
    distributedRuntime.attachRuntime({
        sessionBridge: sessionBroker,
        approvalBridge: approvalBroker,
        automationBridge: automationManager,
    });
    const remoteRunnerRegistry = new RemoteRunnerRegistry(agentManager);
    const remoteSupervisor = new RemoteSupervisor(remoteRunnerRegistry);
    const sandboxSessionRegistry = new SandboxSessionRegistry(workingDirectory);
    const mcpRegistry = new McpRegistry({
        hookDispatcher,
        sandboxSessions: sandboxSessionRegistry,
    });
    mcpRegistry.setRuntimeBus(options.runtimeBus);
    mcpRegistry.setSandboxRuntime(configManager, sandboxSessionRegistry);
    const tokenAuditor = new ApiTokenAuditor({ managed: false });
    const componentHealthMonitor = new ComponentHealthMonitor();
    const worktreeRegistry = new WorktreeRegistry(workingDirectory, { surfaceRoot });
    const webhookNotifier = new WebhookNotifier();
    const replayEngine = new DeterministicReplayEngine(workingDirectory);
    const providerOptimizer = new ProviderOptimizer(providerRegistry, providerCapabilityRegistry, false);
    const sessionMemoryStore = new SessionMemoryStore();
    const sessionLineageTracker = new SessionLineageTracker();
    const sessionChangeTracker = new SessionChangeTracker();
    const planManager = new ExecutionPlanManager(workingDirectory);
    const adaptivePlanner = new AdaptivePlanner();
    const idempotencyStore = new IdempotencyStore();
    const overflowHandler = new OverflowHandler({ baseDir: workingDirectory });
    const policyRuntimeState = new PolicyRuntimeState();
    const fileCache = new FileStateCache();
    const projectIndex = new ProjectIndex(workingDirectory);
    const channelDeliveryRouter = new ChannelDeliveryRouter({
        configManager,
        serviceRegistry,
        artifactStore,
    });
    const processManager = new ProcessManager();
    const modeManager = new ModeManager();
    const fileUndoManager = new FileUndoManager();
    const integrationHelpers = new IntegrationHelperService({
        workingDirectory,
        homeDirectory,
        runtimeStore: options.runtimeStore,
        runtimeBus: options.runtimeBus,
        configManager,
        getConversationTitle: options.getConversationTitle,
        automationManager,
        approvalBroker,
        sessionBroker,
        distributedRuntime,
        remoteRunnerRegistry,
        remoteSupervisor,
        panelManager,
        localUserAuthManager,
        providerRegistry,
        serviceRegistry,
        subscriptionManager,
        secretsManager,
    });
    agentOrchestrator.setDependencies({
        fileCache,
        projectIndex,
        workingDirectory,
        surfaceRoot,
        fileUndoManager,
        modeManager,
        processManager,
        agentMessageBus,
        webSearchService,
        channelRegistry: channelPlugins,
        remoteRunnerRegistry,
        knowledgeService,
        memoryRegistry,
        archetypeLoader,
        configManager,
        providerRegistry,
        providerOptimizer,
        toolLLM,
        serviceRegistry,
        sessionOrchestration,
        featureFlags,
        overflowHandler,
        sandboxSessionRegistry,
        workflowServices: workflow,
    });
    return {
        workingDirectory,
        homeDirectory,
        shellPaths,
        configManager,
        featureFlags,
        runtimeBus: options.runtimeBus,
        runtimeStore: options.runtimeStore,
        runtimeDispatch,
        panelManager,
        keybindingsManager,
        routeBindings,
        surfaceRegistry,
        channelPlugins,
        channelDeliveryRouter,
        watcherRegistry,
        approvalBroker,
        sessionBroker,
        deliveryManager,
        automationManager,
        gatewayMethods,
        artifactStore,
        knowledgeService,
        memoryStore,
        memoryRegistry,
        serviceRegistry,
        secretsManager,
        subscriptionManager,
        localUserAuthManager,
        profileManager,
        bookmarkManager,
        sessionManager,
        sessionOrchestration,
        hookDispatcher,
        hookActivityTracker,
        hookWorkbench,
        pluginManager,
        workflow,
        voiceProviders,
        voiceService,
        webSearchProviders,
        webSearchService,
        mediaProviders,
        multimodalService,
        memoryEmbeddingRegistry,
        channelPolicy,
        mcpRegistry,
        tokenAuditor,
        componentHealthMonitor,
        worktreeRegistry,
        sandboxSessionRegistry,
        webhookNotifier,
        replayEngine,
        providerOptimizer,
        providerCapabilityRegistry,
        cacheHitTracker,
        favoritesStore,
        benchmarkStore,
        modelLimitsService,
        providerRegistry,
        toolLLM,
        distributedRuntime,
        remoteRunnerRegistry,
        remoteSupervisor,
        sessionMemoryStore,
        sessionLineageTracker,
        sessionChangeTracker,
        planManager,
        adaptivePlanner,
        idempotencyStore,
        overflowHandler,
        policyRuntimeState,
        archetypeLoader,
        agentManager,
        agentMessageBus,
        agentOrchestrator,
        wrfcController,
        processManager,
        modeManager,
        fileUndoManager,
        integrationHelpers,
    };
}
