import * as fs from 'fs';
import * as path from 'path';
import * as toml from 'toml';
import { homedir } from 'os';
import { isLocalhostAddress } from './core/security-utils.js';
function expandTilde(filepath) {
    if (filepath.startsWith('~')) {
        return path.join(homedir(), filepath.slice(1));
    }
    return filepath;
}
function validatePort(port) {
    return Number.isInteger(port) && port >= 1024 && port <= 65535;
}
function validateConfig(config) {
    if (config.port !== undefined) {
        if (!validatePort(config.port)) {
            return {
                valid: false,
                error: `Invalid port: ${config.port}. Port must be between 1024 and 65535.`
            };
        }
    }
    if (config.projectDir !== undefined && typeof config.projectDir !== 'string') {
        return {
            valid: false,
            error: `Invalid projectDir: must be a string.`
        };
    }
    if (config.dashboardOnly !== undefined && typeof config.dashboardOnly !== 'boolean') {
        return {
            valid: false,
            error: `Invalid dashboardOnly: must be a boolean.`
        };
    }
    if (config.lang !== undefined && typeof config.lang !== 'string') {
        return {
            valid: false,
            error: `Invalid lang: must be a string.`
        };
    }
    // Validate network configuration
    if (config.bindAddress !== undefined && typeof config.bindAddress !== 'string') {
        return {
            valid: false,
            error: `Invalid bindAddress: must be a valid IP address string.`
        };
    }
    if (config.allowExternalAccess !== undefined && typeof config.allowExternalAccess !== 'boolean') {
        return {
            valid: false,
            error: `Invalid allowExternalAccess: must be a boolean.`
        };
    }
    // Network security validation: if binding to non-localhost address, require explicit allowExternalAccess
    if (config.bindAddress !== undefined && !isLocalhostAddress(config.bindAddress) && !config.allowExternalAccess) {
        return {
            valid: false,
            error: `Network security: binding to '${config.bindAddress}' (non-localhost) requires explicit allowExternalAccess = true. This exposes your dashboard to network access.`
        };
    }
    // Validate security features
    if (config.security !== undefined) {
        const sec = config.security;
        if (sec.rateLimitPerMinute !== undefined && (typeof sec.rateLimitPerMinute !== 'number' || sec.rateLimitPerMinute < 1)) {
            return {
                valid: false,
                error: `Invalid security.rateLimitPerMinute: must be a positive number.`
            };
        }
        if (sec.auditLogRetentionDays !== undefined && (typeof sec.auditLogRetentionDays !== 'number' || sec.auditLogRetentionDays < 1)) {
            return {
                valid: false,
                error: `Invalid security.auditLogRetentionDays: must be a positive number.`
            };
        }
    }
    return { valid: true };
}
export function loadConfigFromPath(configPath) {
    try {
        const expandedPath = expandTilde(configPath);
        if (!fs.existsSync(expandedPath)) {
            return {
                config: null,
                configPath: expandedPath,
                error: `Config file not found: ${expandedPath}`
            };
        }
        const configContent = fs.readFileSync(expandedPath, 'utf-8');
        const parsedConfig = toml.parse(configContent);
        const validation = validateConfig(parsedConfig);
        if (!validation.valid) {
            return {
                config: null,
                configPath: expandedPath,
                error: validation.error
            };
        }
        const config = {};
        if (parsedConfig.projectDir !== undefined) {
            config.projectDir = expandTilde(parsedConfig.projectDir);
        }
        if (parsedConfig.port !== undefined) {
            config.port = parsedConfig.port;
        }
        if (parsedConfig.bindAddress !== undefined) {
            config.bindAddress = parsedConfig.bindAddress;
        }
        if (parsedConfig.allowExternalAccess !== undefined) {
            config.allowExternalAccess = parsedConfig.allowExternalAccess;
        }
        if (parsedConfig.dashboardOnly !== undefined) {
            config.dashboardOnly = parsedConfig.dashboardOnly;
        }
        if (parsedConfig.lang !== undefined) {
            config.lang = parsedConfig.lang;
        }
        if (parsedConfig.security !== undefined) {
            config.security = parsedConfig.security;
        }
        return {
            config,
            configPath: expandedPath
        };
    }
    catch (error) {
        if (error instanceof Error) {
            return {
                config: null,
                configPath: null,
                error: `Failed to load config file: ${error.message}`
            };
        }
        return {
            config: null,
            configPath: null,
            error: 'Failed to load config file: Unknown error'
        };
    }
}
export function loadConfigFile(projectDir, customConfigPath) {
    // If custom config path is provided, use it
    if (customConfigPath) {
        return loadConfigFromPath(customConfigPath);
    }
    // Otherwise, look for default config in project directory
    try {
        const expandedDir = expandTilde(projectDir);
        const configDir = path.join(expandedDir, '.spec-workflow');
        const configPath = path.join(configDir, 'config.toml');
        if (!fs.existsSync(configPath)) {
            return {
                config: null,
                configPath: null
            };
        }
        return loadConfigFromPath(configPath);
    }
    catch (error) {
        if (error instanceof Error) {
            return {
                config: null,
                configPath: null,
                error: `Failed to load config file: ${error.message}`
            };
        }
        return {
            config: null,
            configPath: null,
            error: 'Failed to load config file: Unknown error'
        };
    }
}
export function mergeConfigs(fileConfig, cliArgs) {
    const merged = {};
    if (fileConfig) {
        Object.assign(merged, fileConfig);
    }
    Object.keys(cliArgs).forEach(key => {
        const value = cliArgs[key];
        if (value !== undefined) {
            merged[key] = value;
        }
    });
    return merged;
}
//# sourceMappingURL=config.js.map