/**
 * YAML serialization helpers for the benchmark export (and any other page
 * that builds YAML client-side).
 *
 * Extracted from benchmark_results.html so the escaping is unit-testable —
 * these functions are load-bearing for export correctness (a regression in
 * yamlEscape would silently corrupt every downloaded benchmark YAML).
 *
 * Loaded as a classic <script src> (functions become browser globals) with a
 * module.exports shim at the bottom so vitest can import them — same dual-use
 * pattern as security/url-validator.js, config/urls.js, etc.
 */

// Escape a string for use inside a YAML double-quoted scalar. Backslash MUST
// be escaped first, otherwise the backslashes added by the later replacements
// would themselves get doubled.
function yamlEscape(str) {
    if (str == null) return '';
    return String(str)
        .replace(/\\/g, '\\\\')
        .replace(/"/g, '\\"')
        .replace(/\n/g, '\\n')
        .replace(/\r/g, '\\r')
        .replace(/\t/g, '\\t');
}

// Format a single setting value as a YAML scalar / flow node.
// Booleans/numbers emit bare; null as `null`; arrays/objects as inline JSON
// (valid YAML 1.2 flow syntax — JSON is a YAML 1.2 superset). Strings are
// always double-quoted via yamlEscape so colons, hashes, leading dashes,
// and YAML reserved words (true/no/null/~) are unambiguous.
function formatSettingValue(value) {
    if (value === null || value === undefined) return 'null';
    if (typeof value === 'boolean') return value ? 'true' : 'false';
    if (typeof value === 'number') {
        if (!Number.isFinite(value)) return 'null';
        return String(value);
    }
    if (Array.isArray(value) || typeof value === 'object') {
        try {
            return JSON.stringify(value);
        } catch (_e) {
            // Defensive: circular references etc. Fall back to null.
            return 'null';
        }
    }
    return `"${yamlEscape(value)}"`;
}

// Build a `settings:` YAML block from a redacted settings snapshot dict.
// Snapshot is the {key: {value, ui_element, type, ...}} nested-with-metadata
// shape produced by SettingsManager.get_all_settings(). Tolerates flat
// snapshots and missing `value` keys without crashing.
function formatSettingsSnapshot(snapshot) {
    if (snapshot == null) {
        return 'settings: null  # snapshot not captured for this run\n';
    }
    const keys = Object.keys(snapshot).sort();
    if (keys.length === 0) return 'settings: {}\n';
    let out = 'settings:\n';
    for (const key of keys) {
        const entry = snapshot[key];
        const raw = (entry && typeof entry === 'object' && 'value' in entry)
            ? entry.value
            : (entry && typeof entry === 'object' ? null : entry);
        // Quote keys containing YAML-significant chars. Plain dotted keys
        // (e.g. `llm.model`) are valid plain scalars — no quoting needed.
        const needsQuote = /[:#\s[\]{},&*!|>'"%@`]/.test(key) || /^[-?]/.test(key);
        const formattedKey = needsQuote ? `"${yamlEscape(key)}"` : key;
        out += `  ${formattedKey}: ${formatSettingValue(raw)}\n`;
    }
    return out;
}

// Browser: expose as globals (classic <script> already does this for top-level
// declarations, but be explicit). Node/vitest: export for unit tests.
if (typeof window !== 'undefined') {
    window.yamlEscape = yamlEscape;
    window.formatSettingValue = formatSettingValue;
    window.formatSettingsSnapshot = formatSettingsSnapshot;
}
if (typeof module !== 'undefined' && module.exports) {
    module.exports = { yamlEscape, formatSettingValue, formatSettingsSnapshot };
}
