// engine/figma/e2e-generator.ts — Generate Playwright E2E tests from Figma flow graph (SPEC-430)
import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const SUPPORTED_TRIGGERS = new Set(['ON_CLICK', 'AFTER_TIMEOUT']);
// ---------------------------------------------------------------------------
// Private helpers
// ---------------------------------------------------------------------------
function toKebabCase(str) {
    return str
        .toLowerCase()
        .replace(/[/\\]/g, '-')
        .replace(/[\s_]+/g, '-')
        .replace(/--+/g, '-')
        .replace(/^-|-$/g, '');
}
function buildOnClickCode(flow) {
    const from = toKebabCase(flow.fromFrameName);
    const to = toKebabCase(flow.toFrameName);
    return [
        `  test('navigates from ${flow.fromFrameName} to ${flow.toFrameName} on click', async ({ page }) => {`,
        `    // TODO: Update selector to match actual implementation`,
        `    await page.click('[data-testid="${from}"]');`,
        `    await expect(page).toHaveURL(/${to}/);`,
        `  });`,
    ].join('\n');
}
function buildAfterTimeoutCode(flow) {
    const to = toKebabCase(flow.toFrameName);
    return [
        `  test('auto-navigates from ${flow.fromFrameName} to ${flow.toFrameName}', async ({ page }) => {`,
        `    // TODO: Adjust timeout to match actual transition delay`,
        `    await page.waitForURL(/${to}/, { timeout: 5000 });`,
        `  });`,
    ].join('\n');
}
// ---------------------------------------------------------------------------
// Public functions
// ---------------------------------------------------------------------------
export function flowToTestCase(flow, index) {
    if (!SUPPORTED_TRIGGERS.has(flow.trigger)) {
        return null;
    }
    const id = `flow-${toKebabCase(flow.section)}-${String(index).padStart(3, '0')}`;
    if (flow.trigger === 'ON_CLICK') {
        const playwrightCode = buildOnClickCode(flow);
        return {
            id,
            description: `navigates from ${flow.fromFrameName} to ${flow.toFrameName} on click`,
            fromFrame: flow.fromFrameName,
            toFrame: flow.toFrameName,
            trigger: flow.trigger,
            section: flow.section,
            playwrightCode,
        };
    }
    // AFTER_TIMEOUT
    const playwrightCode = buildAfterTimeoutCode(flow);
    return {
        id,
        description: `auto-navigates from ${flow.fromFrameName} to ${flow.toFrameName}`,
        fromFrame: flow.fromFrameName,
        toFrame: flow.toFrameName,
        trigger: flow.trigger,
        section: flow.section,
        playwrightCode,
    };
}
export function groupFlowsBySection(flows) {
    const map = new Map();
    for (const flow of flows) {
        const existing = map.get(flow.section);
        if (existing !== undefined) {
            existing.push(flow);
        }
        else {
            map.set(flow.section, [flow]);
        }
    }
    return map;
}
export function generateTestFileContent(section, testCases) {
    const testBlocks = testCases.map((tc) => tc.playwrightCode).join('\n\n');
    return [
        `import { test, expect } from '@playwright/test';`,
        ``,
        `/**`,
        ` * Auto-generated from Figma flows — section: ${section}`,
        ` * Generated by Planu (SPEC-430)`,
        ` * DO NOT EDIT — regenerate with: generate_figma_e2e_tests`,
        ` */`,
        ``,
        `test.describe('${section} flows (Figma)', () => {`,
        `  test.beforeEach(async ({ page }) => {`,
        `    // TODO: Update base URL to your app's URL`,
        `    await page.goto('/');`,
        `  });`,
        ``,
        testBlocks,
        `});`,
        ``,
    ].join('\n');
}
export function generateE2ETests(flows, outputDir) {
    let skippedFlows = 0;
    const testCases = [];
    for (let i = 0; i < flows.length; i++) {
        const flow = flows[i];
        if (flow === undefined) {
            continue;
        }
        const tc = flowToTestCase(flow, i);
        if (tc === null) {
            skippedFlows++;
        }
        else {
            testCases.push(tc);
        }
    }
    const grouped = groupFlowsBySection(flows);
    const files = [];
    for (const [section, sectionFlows] of grouped) {
        const sectionTestCases = testCases.filter((tc) => tc.section === section);
        if (sectionTestCases.length === 0) {
            continue;
        }
        const filename = `figma-${toKebabCase(section)}-flows.spec.ts`;
        const fullContent = generateTestFileContent(section, sectionTestCases);
        files.push({
            filename,
            section,
            testCases: sectionTestCases,
            fullContent,
        });
        // prevent unused variable warning
        void sectionFlows;
    }
    return {
        totalFlows: flows.length,
        totalTestCases: testCases.length,
        files,
        skippedFlows,
        outputDir,
    };
}
export async function writeE2ETestFiles(result, projectPath) {
    const targetDir = join(projectPath, result.outputDir);
    await mkdir(targetDir, { recursive: true });
    const writtenPaths = [];
    for (const file of result.files) {
        const filePath = join(targetDir, file.filename);
        await writeFile(filePath, file.fullContent, 'utf-8');
        writtenPaths.push(filePath);
    }
    return writtenPaths;
}
export function formatE2EReport(result) {
    const fileLines = result.files
        .map((f) => `- \`${f.filename}\` — ${f.testCases.length} test case${f.testCases.length === 1 ? '' : 's'} (${f.section})`)
        .join('\n');
    return [
        `## Figma E2E Test Generation Report`,
        ``,
        `**Total flows analyzed**: ${result.totalFlows}`,
        `**Test cases generated**: ${result.totalTestCases}`,
        `**Flows skipped** (unsupported trigger): ${result.skippedFlows}`,
        `**Output directory**: ${result.outputDir}`,
        ``,
        `### Generated Files`,
        fileLines,
        ``,
        `### Next Steps`,
        `1. Review generated tests in \`${result.outputDir}\``,
        `2. Update \`data-testid\` selectors to match your implementation`,
        `3. Update base URL in \`beforeEach\``,
        `4. Run: \`npx playwright test ${result.outputDir}\``,
    ].join('\n');
}
//# sourceMappingURL=e2e-generator.js.map