/**
 * TestCase → Playwright .spec.ts translator.
 *
 * Renders a list of TestCase objects into a single Playwright spec
 * file. The output file imports from `@specverse/runtime/test-harness`
 * and nothing else from the runtime — all logic lives in the harness
 * helpers. The translator is intentionally dumb: each step maps to a
 * helper call, nothing more.
 */
/**
 * Render a single step as a line of test body code.
 */
function renderStep(step) {
    switch (step.action) {
        case 'bootRuntime':
            // Assign `page` once per test body. Multiple bootRuntime steps
            // inside one test aren't supported and would shadow the binding.
            return `  const { page } = await bootRuntime(browser);`;
        case 'expectNavHasModel':
            return `  await expectNavHasModel(page, ${JSON.stringify(step.modelName)});`;
        case 'navigateToModel':
            return `  await navigateToModel(page, ${JSON.stringify(step.modelName)});`;
        case 'navigateToModelForm':
            return `  await navigateToModelForm(page, ${JSON.stringify(step.modelName)});`;
        case 'navigateToModelDetail':
            return `  await navigateToModelDetail(page, ${JSON.stringify(step.modelName)});`;
        case 'expectViewRenders':
            return `  await expectViewRenders(page);`;
        case 'expectListColumn':
            return `  await expectListColumn(page, ${JSON.stringify(step.modelName)}, ${JSON.stringify(step.attributeName)});`;
        case 'expectFormInput': {
            const opts = step.required ? `, { required: true }` : ``;
            return `  await expectFormInput(page, ${JSON.stringify(step.modelName)}, ${JSON.stringify(step.attributeName)}${opts});`;
        }
        case 'expectLifecycleState':
            return `  await expectLifecycleState(page, ${JSON.stringify(step.modelName)}, ${JSON.stringify(step.stateName)});`;
        case 'expectRelationshipSection':
            return `  await expectRelationshipSection(page, ${JSON.stringify(step.modelName)}, ${JSON.stringify(step.relationshipName)});`;
        case 'expectActionButton':
            return `  await expectActionButton(page, ${JSON.stringify(step.modelName)}, ${JSON.stringify(step.actionLabel)});`;
        case 'createEntity': {
            const varName = step.bindAs || 'created';
            const dataLit = JSON.stringify(step.data);
            const optsLit = step.uniqueField
                ? `, { uniqueField: ${JSON.stringify(step.uniqueField)} }`
                : '';
            return `  const ${varName} = await createEntity(page, ${JSON.stringify(step.modelName)}, ${dataLit}${optsLit});`;
        }
        case 'deleteEntity':
            return `  await deleteEntity(page, ${JSON.stringify(step.modelName)}, ${step.idExpr});`;
        case 'evolveEntity':
            return `  await evolveEntity(page, ${JSON.stringify(step.modelName)}, ${step.idExpr}, ${JSON.stringify(step.targetState)});`;
        case 'expectEntityInList': {
            const display = step.displayExpr ?? JSON.stringify(step.displayValue ?? '');
            return `  await expectEntityInList(page, ${JSON.stringify(step.modelName)}, ${display});`;
        }
        case 'expectEntityAbsent': {
            const display = step.displayExpr ?? JSON.stringify(step.displayValue ?? '');
            return `  await expectEntityAbsent(page, ${JSON.stringify(step.modelName)}, ${display});`;
        }
        default: {
            const _exhaustive = step;
            throw new Error(`translator: unknown step action: ${JSON.stringify(_exhaustive)}`);
        }
    }
}
/**
 * Collect the set of harness helpers a test case depends on so the
 * import list only contains what's actually used.
 */
function helpersFor(step) {
    switch (step.action) {
        case 'bootRuntime':
            return ['bootRuntime'];
        case 'expectNavHasModel':
            return ['expectNavHasModel'];
        case 'navigateToModel':
            return ['navigateToModel'];
        case 'navigateToModelForm':
            return ['navigateToModelForm'];
        case 'navigateToModelDetail':
            return ['navigateToModelDetail'];
        case 'expectViewRenders':
            return ['expectViewRenders'];
        case 'expectListColumn':
            return ['expectListColumn'];
        case 'expectFormInput':
            return ['expectFormInput'];
        case 'expectLifecycleState':
            return ['expectLifecycleState'];
        case 'expectRelationshipSection':
            return ['expectRelationshipSection'];
        case 'expectActionButton':
            return ['expectActionButton'];
        case 'createEntity':
            return ['createEntity'];
        case 'deleteEntity':
            return ['deleteEntity'];
        case 'evolveEntity':
            return ['evolveEntity'];
        case 'expectEntityInList':
            return ['expectEntityInList'];
        case 'expectEntityAbsent':
            return ['expectEntityAbsent'];
        default:
            return [];
    }
}
/**
 * Render a full `.spec.ts` file for one or more test cases sharing
 * the same rule. One file per rule keeps failures easy to attribute
 * and lets `npx playwright test` filter by rule ID via file glob.
 */
export function renderSpecFile(ruleId, testCases) {
    const helpers = new Set();
    for (const tc of testCases) {
        for (const step of tc.steps) {
            for (const h of helpersFor(step))
                helpers.add(h);
        }
    }
    const importList = [...helpers].sort().join(', ');
    const header = `/**
 * Auto-generated UI contract test file.
 * Rule: ${ruleId}
 * DO NOT EDIT — regenerated every \`spv realize\` run. Hand edits are
 * lost on the next regenerate. Change the rule or the spec instead.
 */

import { test } from '@playwright/test';
import { ${importList} } from '@specverse/runtime/test-harness';
`;
    const body = testCases.map(tc => {
        const stepLines = tc.steps.map(renderStep).join('\n');
        return `
test(${JSON.stringify(tc.name)}, async ({ browser }) => {
${stepLines}
});`;
    }).join('\n');
    return header + body + '\n';
}
//# sourceMappingURL=translator.js.map