/**
 * Tests for utils/yaml_export.js — the YAML serialization helpers used by the
 * benchmark export (yamlEscape / formatSettingValue / formatSettingsSnapshot).
 *
 * These are load-bearing for export correctness: a regression in yamlEscape
 * would silently corrupt every downloaded benchmark YAML (and could let a
 * model name / URL with YAML-special chars inject an unintended key). This
 * pins the escaping behaviour now that the function is importable.
 */

import '@js/utils/yaml_export.js';

const { yamlEscape, formatSettingValue, formatSettingsSnapshot } = window;

describe('yamlEscape', () => {
    it('returns empty string for null/undefined', () => {
        expect(yamlEscape(null)).toBe('');
        expect(yamlEscape(undefined)).toBe('');
    });

    it('leaves plain strings untouched', () => {
        expect(yamlEscape('qwen3.6')).toBe('qwen3.6');
    });

    it('escapes backslash FIRST so later escapes are not double-escaped', () => {
        // A lone backslash must become exactly two, not four.
        expect(yamlEscape('a\\b')).toBe('a\\\\b');
        // Backslash + quote: backslash doubled, quote escaped — order matters.
        expect(yamlEscape('\\"')).toBe('\\\\\\"');
    });

    it('escapes double quotes, newlines, CR and tabs', () => {
        expect(yamlEscape('he said "hi"')).toBe('he said \\"hi\\"');
        expect(yamlEscape('a\nb')).toBe('a\\nb');
        expect(yamlEscape('a\rb')).toBe('a\\rb');
        expect(yamlEscape('a\tb')).toBe('a\\tb');
    });

    it('coerces non-strings via String()', () => {
        expect(yamlEscape(42)).toBe('42');
    });
});

describe('formatSettingValue', () => {
    it('emits null for null/undefined', () => {
        expect(formatSettingValue(null)).toBe('null');
        expect(formatSettingValue(undefined)).toBe('null');
    });

    it('emits bare booleans and finite numbers', () => {
        expect(formatSettingValue(true)).toBe('true');
        expect(formatSettingValue(false)).toBe('false');
        expect(formatSettingValue(128000)).toBe('128000');
    });

    it('emits null for non-finite numbers', () => {
        expect(formatSettingValue(Infinity)).toBe('null');
        expect(formatSettingValue(NaN)).toBe('null');
    });

    it('emits inline JSON for arrays and objects', () => {
        expect(formatSettingValue([1, 'a'])).toBe('[1,"a"]');
        expect(formatSettingValue({ a: 1 })).toBe('{"a":1}');
    });

    it('double-quotes and escapes strings', () => {
        expect(formatSettingValue('gpt-4')).toBe('"gpt-4"');
        // A value with a YAML-special char must stay a single safe scalar.
        expect(formatSettingValue('a: b # c')).toBe('"a: b # c"');
        expect(formatSettingValue('inject\nkey: pwned')).toBe(
            '"inject\\nkey: pwned"',
        );
    });
});

describe('formatSettingsSnapshot', () => {
    it('renders a sentinel comment for a null snapshot', () => {
        expect(formatSettingsSnapshot(null)).toBe(
            'settings: null  # snapshot not captured for this run\n',
        );
    });

    it('renders an empty flow map for {}', () => {
        expect(formatSettingsSnapshot({})).toBe('settings: {}\n');
    });

    it('renders sorted keys with formatted values (metadata shape)', () => {
        const out = formatSettingsSnapshot({
            'llm.model': { value: 'qwen3.6', ui_element: 'select' },
            'a.flag': { value: true, ui_element: 'checkbox' },
        });
        // a.flag sorts before llm.model; string quoted, bool bare.
        expect(out).toBe(
            'settings:\n  a.flag: true\n  llm.model: "qwen3.6"\n',
        );
    });

    it('quotes keys that contain YAML-significant characters', () => {
        const out = formatSettingsSnapshot({ 'has space': { value: 'x' } });
        expect(out).toContain('"has space": "x"');
    });

    it('passes flat (non-metadata) scalar values through', () => {
        const out = formatSettingsSnapshot({ 'llm.model': 'qwen3.6' });
        expect(out).toBe('settings:\n  llm.model: "qwen3.6"\n');
    });

    it('renders null for a metadata object missing its `value` key', () => {
        const out = formatSettingsSnapshot({
            'llm.model': { ui_element: 'select' },
        });
        expect(out).toBe('settings:\n  llm.model: null\n');
    });
});
