import { config as loadEnv } from 'dotenv';
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { homedir } from 'os';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { loadAllMCPConfigs, loadAllProviderConfigs, } from '../config/mcp-config-loader.js';
import { getConfigPath } from '../config/paths.js';
import { loadPreferences } from '../config/preferences.js';
import { defaultTheme, getThemeColors } from '../config/themes.js';
import { logError } from '../utils/message-queue.js';
// Load .env file from working directory (shell environment takes precedence)
// Suppress dotenv console output by temporarily redirecting stdout
const envPath = join(process.cwd(), '.env');
if (existsSync(envPath)) {
    const originalWrite = process.stdout.write.bind(process.stdout);
    process.stdout.write = () => true;
    try {
        loadEnv({ path: envPath });
    }
    finally {
        process.stdout.write = originalWrite;
    }
}
// Hold a map of what config files are where
export const confDirMap = {};
// Find the closest config file for the requested configuration file
export function getClosestConfigFile(fileName) {
    try {
        const configDir = getConfigPath();
        // If NANOCODER_CONFIG_DIR is explicitly set, skip cwd and home checks
        // and use only the config directory (important for tests and explicit overrides)
        const isExplicitConfigDir = Boolean(process.env.NANOCODER_CONFIG_DIR);
        if (!isExplicitConfigDir) {
            // First, lets check for a working directory config
            const cwdPath = join(process.cwd(), fileName); // nosemgrep
            if (existsSync(cwdPath)) {
                // nosemgrep
                confDirMap[fileName] = cwdPath; // nosemgrep
                return cwdPath; // nosemgrep
            }
            // Next lets check the $HOME for a hidden file. This should only be for
            // legacy support
            const homePath = join(homedir(), `.${fileName}`); // nosemgrep
            if (existsSync(homePath)) {
                // nosemgrep
                confDirMap[fileName] = homePath; // nosemgrep
                return homePath; // nosemgrep
            }
        }
        // Last, lets look for an user level config.
        // If the file doesn't exist, create it
        const configPath = join(configDir, fileName); // nosemgrep
        if (!existsSync(configPath)) {
            // nosemgrep
            createDefaultConfFile(configDir, fileName);
        }
        confDirMap[fileName] = configPath; // nosemgrep
        return configPath; // nosemgrep
    }
    catch (error) {
        logError(`Failed to load ${fileName}: ${String(error)}`);
    }
    // The code should never hit this, but it makes the TS compiler happy.
    return fileName;
}
function createDefaultConfFile(filePath, fileName) {
    try {
        // If we cant find any, lets assume this is the first user run, create the
        // correct file and direct the user to configure them correctly,
        const configFilePath = join(filePath, fileName); // nosemgrep
        if (!existsSync(configFilePath)) {
            // nosemgrep
            // Maybe add a better sample config?
            const sampleConfig = {};
            mkdirSync(filePath, { recursive: true });
            writeFileSync(configFilePath, // nosemgrep
            JSON.stringify(sampleConfig, null, 2), 'utf-8');
        }
    }
    catch (error) {
        logError(`Failed to write ${filePath}: ${String(error)}`);
    }
}
// Try to load auto-compact config from a specific path
// Returns the config if found and valid, null otherwise
function tryLoadAutoCompactFromPath(configPath, defaults) {
    if (!existsSync(configPath)) {
        return null;
    }
    try {
        const rawData = readFileSync(configPath, 'utf-8');
        const config = JSON.parse(rawData);
        const autoCompact = config.nanocoder?.autoCompact;
        if (autoCompact && typeof autoCompact === 'object') {
            return {
                enabled: autoCompact.enabled !== undefined
                    ? Boolean(autoCompact.enabled)
                    : defaults.enabled,
                threshold: validateThreshold(autoCompact.threshold ?? defaults.threshold),
                mode: validateMode(autoCompact.mode ?? defaults.mode),
                notifyUser: autoCompact.notifyUser !== undefined
                    ? Boolean(autoCompact.notifyUser)
                    : defaults.notifyUser,
            };
        }
    }
    catch (error) {
        logError(`Failed to load auto-compact config from ${configPath}: ${String(error)}`);
    }
    return null;
}
// Load auto-compact configuration and Returns default config if not specified
function loadAutoCompactConfig() {
    const defaults = {
        enabled: true,
        threshold: 60,
        mode: 'conservative',
        notifyUser: true,
    };
    // Try to load from project-level config first
    const projectConfigPath = join(process.cwd(), 'agents.config.json');
    const projectConfig = tryLoadAutoCompactFromPath(projectConfigPath, defaults);
    if (projectConfig) {
        return projectConfig;
    }
    // Try global config
    const configDir = getConfigPath();
    const globalConfigPath = join(configDir, 'agents.config.json');
    const globalConfig = tryLoadAutoCompactFromPath(globalConfigPath, defaults);
    if (globalConfig) {
        return globalConfig;
    }
    // Fallback to home directory
    const homePath = join(homedir(), '.agents.config.json');
    const homeConfig = tryLoadAutoCompactFromPath(homePath, defaults);
    if (homeConfig) {
        return homeConfig;
    }
    return defaults;
}
// Validate and clamp threshold to valid range (50-95)
function validateThreshold(threshold) {
    const num = typeof threshold === 'number' ? threshold : 60;
    return Math.max(50, Math.min(95, Math.round(num)));
}
// Validate compression mode
function validateMode(mode) {
    if (mode === 'default' || mode === 'aggressive' || mode === 'conservative') {
        return mode;
    }
    return 'conservative';
}
// Function to load app configuration from agents.config.json if it exists
function loadAppConfig() {
    // Load providers from the new hierarchical configuration system
    const providers = loadAllProviderConfigs();
    // Load MCP servers from the new hierarchical configuration system
    const mcpServersWithSource = loadAllMCPConfigs();
    const mcpServers = mcpServersWithSource.map(item => item.server);
    // Load auto-compact configuration
    const autoCompact = loadAutoCompactConfig();
    return {
        providers,
        mcpServers,
        autoCompact,
    };
}
let _appConfig = null;
/**
 * Lazy-loaded app config to avoid circular dependencies during module initialization
 * @public
 */
export function getAppConfig() {
    if (!_appConfig) {
        _appConfig = loadAppConfig();
    }
    return _appConfig;
}
// Legacy export for backward compatibility - use a getter
export const appConfig = new Proxy({}, {
    get(_target, prop) {
        return getAppConfig()[prop];
    },
});
// Function to reload the app configuration (useful after config file changes)
export function reloadAppConfig() {
    _appConfig = loadAppConfig();
}
// Function to clear the cached app configuration (useful for testing)
export function clearAppConfig() {
    _appConfig = null;
}
let cachedColors = null;
export function getColors() {
    if (!cachedColors) {
        const preferences = loadPreferences();
        const selectedTheme = preferences.selectedTheme || defaultTheme;
        cachedColors = getThemeColors(selectedTheme);
    }
    return cachedColors;
}
// Legacy export for backwards compatibility - use a getter to avoid circular dependency
export const colors = new Proxy({}, {
    get(_target, prop) {
        return getColors()[prop];
    },
});
// Get the package root directory (where this module is installed)
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Go up from dist/config to package root, then to source/app/prompts/main-prompt.md
// This works because source/app/prompts/main-prompt.md is included in the package.json files array
export const promptPath = join(__dirname, '../../source/app/prompts/main-prompt.md');
//# sourceMappingURL=index.js.map