// engine/spec-format/bdd-parser.ts — BDD/Gherkin parser and emitter (SPEC-481)
const KEYWORD_MAP = {
    given: 'given',
    when: 'when',
    then: 'then',
    and: 'and',
    but: 'and',
};
/**
 * Parses Gherkin-style blocks from a markdown string.
 *
 * Recognises:
 *   Scenario: <title>
 *     Given ...
 *     When ...
 *     Then ...
 *     And ...
 *     But ...
 */
export function parseBddScenarios(markdown) {
    const scenarios = [];
    const lines = markdown.split('\n');
    let current = null;
    // Tracks whether the current scenario was auto-created (no Scenario: header)
    let currentIsHeaderless = false;
    for (const raw of lines) {
        const line = raw.trim();
        // Detect scenario header
        const scenarioMatch = /^scenario:\s*(.+)$/i.exec(line);
        if (scenarioMatch) {
            if (current) {
                scenarios.push(current);
            }
            current = { title: (scenarioMatch[1] ?? '').trim(), steps: [], done: false };
            currentIsHeaderless = false;
            continue;
        }
        // Detect step keywords
        const stepMatch = /^(given|when|then|and|but)\s+(.+)$/i.exec(line);
        if (!stepMatch) {
            continue;
        }
        const rawKeyword = (stepMatch[1] ?? '').toLowerCase();
        const keyword = KEYWORD_MAP[rawKeyword] ?? 'and';
        const text = (stepMatch[2] ?? '').trim();
        // A new block starts when GIVEN appears and there is already an active scenario with
        // steps. This handles both multiple headerless blocks and headerless blocks following
        // an explicit Scenario: header block.
        if (rawKeyword === 'given' && current !== null && current.steps.length > 0) {
            scenarios.push(current);
            current = null;
            currentIsHeaderless = false;
        }
        // Auto-create a scenario when a step is found without a preceding Scenario header
        if (!current) {
            current = { title: text, steps: [], done: false };
            currentIsHeaderless = true;
        }
        current.steps.push({ keyword, text });
        // For headerless scenarios, update the title to the THEN text for better descriptiveness
        if (currentIsHeaderless && keyword === 'then') {
            current.title = text;
        }
    }
    if (current) {
        scenarios.push(current);
    }
    return scenarios;
}
/**
 * Converts an array of BddScenario objects into YAML lines for the frontmatter.
 *
 * Output format:
 *   scenarios:
 *     - title: "..."
 *       done: false
 *       steps:
 *         - keyword: given
 *           text: "..."
 */
export function renderBddScenariosYaml(scenarios) {
    const lines = ['scenarios:'];
    for (const scenario of scenarios) {
        lines.push(`  - title: "${escapeYaml(scenario.title)}"`);
        lines.push(`    done: ${String(scenario.done)}`);
        if (scenario.tests && scenario.tests.length > 0) {
            lines.push(`    tests:`);
            for (const test of scenario.tests) {
                lines.push(`      - path: ${test.path}`);
                if (test.line !== undefined) {
                    lines.push(`        line: ${String(test.line)}`);
                }
            }
        }
        lines.push(`    steps:`);
        for (const step of scenario.steps) {
            lines.push(`      - keyword: ${step.keyword}`);
            lines.push(`        text: "${escapeYaml(step.text)}"`);
        }
    }
    return lines;
}
/**
 * Converts checkbox-style criteria into BDD scenarios.
 * Generates a full GIVEN/WHEN/THEN structure instead of THEN-only.
 * Plain text criteria get a generic GIVEN (system context) and WHEN (action trigger)
 * so scenarios are always structurally valid BDD.
 */
export function convertCheckboxToBdd(criteria) {
    return criteria.map((criterion) => ({
        title: criterion.text,
        steps: [
            { keyword: 'given', text: 'the system is in its default state' },
            { keyword: 'when', text: 'the described behavior is triggered' },
            { keyword: 'then', text: criterion.text },
        ],
        done: criterion.done,
    }));
}
function escapeYaml(value) {
    return value.replace(/"/g, '\\"');
}
//# sourceMappingURL=bdd-parser.js.map