/**
 * Settings Service
 *
 * Server-side key-value settings persisted to SQLite.
 * Used for workspace-wide configuration that needs to be accessible server-side,
 * such as default executable paths for agent providers.
 *
 * Settings are stored in the `settings` table as JSON-encoded values.
 */
import { createLogger } from '../utils/logger.js';
const logger = createLogger('settings-service');
/**
 * Well-known setting keys
 */
export const SETTING_KEYS = {
    AGENT_DEFAULTS: 'agentDefaults',
};
// ============================================================================
// Implementation
// ============================================================================
function dbToSetting(row) {
    let parsedValue;
    try {
        parsedValue = JSON.parse(row.value);
    }
    catch {
        parsedValue = row.value;
    }
    return {
        key: row.key,
        value: parsedValue,
        updatedAt: row.updated_at,
    };
}
const DEFAULT_AGENT_DEFAULTS = {
    defaultExecutablePaths: {},
};
export function createSettingsService(storage) {
    return {
        getSetting(key) {
            const row = storage.queryOne('SELECT key, value, updated_at FROM settings WHERE key = ?', [key]);
            if (!row)
                return undefined;
            return dbToSetting(row);
        },
        setSetting(key, value) {
            const jsonValue = JSON.stringify(value);
            const updatedAt = new Date().toISOString();
            storage.run('INSERT INTO settings (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at', [key, jsonValue, updatedAt]);
            logger.debug(`Setting updated: ${key}`);
            return {
                key,
                value,
                updatedAt,
            };
        },
        deleteSetting(key) {
            const result = storage.run('DELETE FROM settings WHERE key = ?', [key]);
            return result.changes > 0;
        },
        getAgentDefaults() {
            const setting = this.getSetting(SETTING_KEYS.AGENT_DEFAULTS);
            if (!setting) {
                return { ...DEFAULT_AGENT_DEFAULTS };
            }
            // Validate shape — ensure defaultExecutablePaths exists and is an object
            const value = setting.value;
            const paths = value?.defaultExecutablePaths;
            const result = {
                defaultExecutablePaths: paths && typeof paths === 'object' && !Array.isArray(paths)
                    ? paths
                    : {},
            };
            // Include fallbackChain if it's a valid array
            if (Array.isArray(value?.fallbackChain)) {
                result.fallbackChain = value.fallbackChain.filter((entry) => typeof entry === 'string');
            }
            return result;
        },
        setAgentDefaults(defaults) {
            // Validate that defaultExecutablePaths is a plain object of strings
            const paths = defaults.defaultExecutablePaths ?? {};
            const sanitized = {};
            for (const [provider, path] of Object.entries(paths)) {
                if (typeof path === 'string') {
                    sanitized[provider] = path;
                }
            }
            const validated = {
                defaultExecutablePaths: sanitized,
            };
            // Validate fallbackChain — must be an array; filter out non-string entries
            if (Array.isArray(defaults.fallbackChain)) {
                validated.fallbackChain = defaults.fallbackChain.filter((entry) => typeof entry === 'string');
            }
            this.setSetting(SETTING_KEYS.AGENT_DEFAULTS, validated);
            return validated;
        },
    };
}
//# sourceMappingURL=settings-service.js.map