import { handleSessionRestoration } from "./session.js";
import { setGlobalLogger } from "../utils/globalLogger.js";
import { LspManager } from "../managers/lspManager.js";
import { USER_MEMORY_FILE } from "../utils/constants.js";
export class InitializationService {
    static async initialize(context, options) {
        const { skillManager, subagentManager, container, toolManager, pluginManager, options: agentOptions, slashCommandManager, logger, mcpManager, workdir, lspManager, configurationService, hookManager, messageManager, memoryRuleManager, liveConfigManager, taskManager, setProjectMemory, setUserMemory, resolveAndValidateConfig, } = context;
        const startTime = performance.now();
        // Initialize managers first
        try {
            const phaseStart = performance.now();
            // Initialize SkillManager
            await skillManager.initialize();
            // Initialize SubagentManager (load and cache configurations)
            await subagentManager.initialize();
            // Register managers in container for tool access
            container.register("SubagentManager", subagentManager);
            container.register("SkillManager", skillManager);
            // Initialize built-in tools
            toolManager.initializeBuiltInTools();
            // Initialize plugins
            await pluginManager.loadPlugins(agentOptions.plugins || []);
            // Register skill commands
            slashCommandManager.registerSkillCommands(skillManager.getAvailableSkills());
            logger?.debug(`Initialization Phase [Managers and Tools] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
        }
        catch (error) {
            logger?.error("Failed to initialize managers and tools:", error);
            // Don't throw error to prevent app startup failure
        }
        // Initialize MCP servers with auto-connect
        try {
            const phaseStart = performance.now();
            await mcpManager.initialize(workdir, true);
            if (lspManager instanceof LspManager) {
                await lspManager.initialize(workdir);
            }
            logger?.debug(`Initialization Phase [MCP and LSP] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
        }
        catch (error) {
            logger?.error("Failed to initialize MCP servers:", error);
            // Don't throw error to prevent app startup failure
        }
        // Initialize hooks configuration
        try {
            const phaseStart = performance.now();
            // Load hooks configuration using ConfigurationService
            const configResult = await configurationService.loadMergedConfiguration(workdir);
            hookManager.loadConfigurationFromWaveConfig(configResult.configuration);
            // Update plugin manager with enabled plugins configuration
            if (configResult.configuration?.enabledPlugins) {
                pluginManager.updateEnabledPlugins(configResult.configuration.enabledPlugins);
            }
            // Initialize permission manager with loaded rules
            if (configResult.configuration?.permissions) {
                const permissionManager = context.container.get("PermissionManager");
                if (permissionManager) {
                    if (configResult.configuration.permissions.allow) {
                        permissionManager.updateAllowedRules(configResult.configuration.permissions.allow);
                    }
                    if (configResult.configuration.permissions.deny) {
                        permissionManager.updateDeniedRules(configResult.configuration.permissions.deny);
                    }
                    if (configResult.configuration.permissions.permissionMode) {
                        permissionManager.updateConfiguredPermissionMode(configResult.configuration.permissions.permissionMode);
                    }
                    if (configResult.configuration.permissions.additionalDirectories) {
                        permissionManager.updateAdditionalDirectories(configResult.configuration.permissions.additionalDirectories);
                    }
                }
            }
            logger?.debug(`Initialization Phase [Hooks Configuration] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
        }
        catch (error) {
            logger?.error("Failed to initialize hooks system:", error);
            // Don't throw error to prevent app startup failure
        }
        // Trigger WorktreeCreate hook if this is a new worktree
        if (agentOptions.isNewWorktree && hookManager) {
            try {
                logger?.info(`Triggering WorktreeCreate hook for ${agentOptions.worktreeName}...`);
                const hookResults = await hookManager.executeHooks("WorktreeCreate", {
                    event: "WorktreeCreate",
                    projectDir: workdir,
                    timestamp: new Date(),
                    sessionId: messageManager.getSessionId(),
                    transcriptPath: messageManager.getTranscriptPath(),
                    cwd: workdir,
                    worktreeName: agentOptions.worktreeName,
                    env: Object.fromEntries(Object.entries(process.env).filter((e) => e[1] !== undefined)),
                });
                // Process hook results
                hookManager.processHookResults("WorktreeCreate", hookResults, messageManager);
            }
            catch (error) {
                logger?.warn("WorktreeCreate hooks execution failed:", error);
            }
        }
        // Resolve and validate configuration after loading settings.json
        resolveAndValidateConfig();
        // Initialize auto-memory directory
        try {
            const phaseStart = performance.now();
            if (configurationService.resolveAutoMemoryEnabled()) {
                const memoryService = container.get("MemoryService");
                if (memoryService) {
                    await memoryService.ensureAutoMemoryDirectory(workdir);
                    const permissionManager = container.get("PermissionManager");
                    if (permissionManager) {
                        const autoMemoryDir = memoryService.getAutoMemoryDirectory(workdir);
                        permissionManager.addSystemAdditionalDirectory(autoMemoryDir);
                        permissionManager.addSystemAdditionalDirectory(USER_MEMORY_FILE);
                    }
                }
            }
            logger?.debug(`Initialization Phase [Auto-memory Initialization] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
        }
        catch (error) {
            logger?.error("Failed to initialize auto-memory directory:", error);
        }
        // Set global logger for SDK-wide access before discovering rules
        setGlobalLogger(logger || null);
        // Discover modular memory rules
        try {
            const phaseStart = performance.now();
            await memoryRuleManager.discoverRules();
            logger?.debug(`Initialization Phase [Memory Rules Discovery] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
        }
        catch (error) {
            logger?.error("Failed to discover memory rules:", error);
        }
        // Initialize live configuration reload
        try {
            const phaseStart = performance.now();
            await liveConfigManager.initialize();
            logger?.debug(`Initialization Phase [Live Config Initialization] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
        }
        catch (error) {
            logger?.error("Failed to initialize live configuration reload:", error);
            // Don't throw error to prevent app startup failure - continue without live reload
        }
        // Load memory files during initialization
        try {
            const phaseStart = performance.now();
            const memoryService = container.get("MemoryService");
            if (!memoryService) {
                throw new Error("MemoryService not found in container");
            }
            // Load project memory from AGENTS.md
            try {
                const projectMemoryContent = await memoryService.readMemoryFile(workdir);
                setProjectMemory(projectMemoryContent);
            }
            catch (error) {
                logger?.warn("Failed to load project memory file:", error);
                setProjectMemory("");
            }
            // Load user memory
            try {
                const userMemoryContent = await memoryService.getUserMemoryContent();
                setUserMemory(userMemoryContent);
            }
            catch (error) {
                logger?.warn("Failed to load user memory file:", error);
                setUserMemory("");
            }
            logger?.debug(`Initialization Phase [Memory Files Loading] took ${(performance.now() - phaseStart).toFixed(2)}ms`);
        }
        catch (error) {
            // Ensure memory is always initialized even if loading fails
            setProjectMemory("");
            setUserMemory("");
            logger?.error("Failed to load memory files:", error);
            // Don't throw error to prevent app startup failure
        }
        // Handle session restoration or set provided messages
        const sessionPhaseStart = performance.now();
        if (options?.messages) {
            // If messages are provided, use them directly (useful for testing)
            messageManager.setMessages(options.messages);
            // Rebuild usage array from restored messages
            messageManager.rebuildUsageFromMessages(options.messages);
        }
        else {
            // Otherwise, handle session restoration
            const sessionToRestore = await handleSessionRestoration(options?.restoreSessionId, options?.continueLastSession, messageManager.getWorkdir());
            // Rebuild usage array from restored messages
            messageManager.rebuildUsageFromMessages(sessionToRestore?.messages || []);
            if (sessionToRestore) {
                messageManager.initializeFromSession(sessionToRestore);
                // Update task manager with the root session ID to ensure continuity across compressions
                taskManager.setTaskListId(sessionToRestore.rootSessionId || sessionToRestore.id);
                // After session is initialized, load tasks for the session
                const tasks = await taskManager.listTasks();
                agentOptions.callbacks?.onTasksChange?.(tasks);
            }
        }
        logger?.debug(`Initialization Phase [Session Restoration] took ${(performance.now() - sessionPhaseStart).toFixed(2)}ms`);
        logger?.debug(`Total Initialization took ${(performance.now() - startTime).toFixed(2)}ms`);
    }
}
