// engine/test-contract-generator.ts — SPEC-018 contract and mock generators
// Generates API contracts (OpenAPI, GraphQL, Pact, tRPC) and API mocks from spec endpoints.
// === Internal helpers ===
function toPascal(str) {
    return str
        .replace(/[^a-zA-Z0-9\s]/g, '')
        .split(/\s+/)
        .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
        .join('');
}
function toSnake(str) {
    return str.toLowerCase().replace(/[^a-z0-9]/g, '_');
}
// === Contract generation ===
/**
 * Generate an API contract from spec endpoint information.
 */
export function generateContractFromSpec(specTitle, endpoints, format) {
    const content = buildContractContent(specTitle, endpoints, format);
    return { format, content, endpoints };
}
function buildContractContent(title, endpoints, format) {
    if (format === 'openapi') {
        return buildOpenApiContent(title, endpoints);
    }
    if (format === 'graphql-schema') {
        return buildGraphqlContent(title);
    }
    if (format === 'pact') {
        return buildPactContent(title, endpoints);
    }
    return buildTrpcContent(title);
}
function buildOpenApiContent(title, endpoints) {
    const paths = endpoints
        .map((ep) => {
        const method = ep.method.toLowerCase();
        const statusLines = ep.statusCodes
            .map((s) => `        '${s}':\n          description: "${s === 200 ? 'Success' : 'Error'}"`)
            .join('\n');
        return `  ${ep.path}:\n    ${method}:\n      summary: "${title} — ${ep.method} ${ep.path}"\n      responses:\n${statusLines}`;
    })
        .join('\n');
    return `openapi: '3.0.3'\ninfo:\n  title: "${title} API Contract"\n  version: '1.0.0'\npaths:\n${paths}\n`;
}
function buildGraphqlContent(title) {
    const typeName = toPascal(title);
    return [
        `# GraphQL schema for: ${title}`,
        '# Generated by Planu SDD MCP Server',
        '',
        `type ${typeName} {`,
        '  id: ID!',
        '  # TODO: add fields',
        '}',
        '',
        'type Query {',
        `  get${typeName}(id: ID!): ${typeName}`,
        `  list${typeName}s: [${typeName}!]!`,
        '}',
        '',
        'type Mutation {',
        `  create${typeName}(input: Create${typeName}Input!): ${typeName}!`,
        `  update${typeName}(id: ID!, input: Update${typeName}Input!): ${typeName}!`,
        `  delete${typeName}(id: ID!): Boolean!`,
        '}',
        '',
        `input Create${typeName}Input {`,
        '  # TODO: add fields',
        '}',
        '',
        `input Update${typeName}Input {`,
        '  # TODO: add fields',
        '}',
        '',
    ].join('\n');
}
function buildPactContent(title, endpoints) {
    const interactions = endpoints.map((ep) => ({
        description: `${ep.method} ${ep.path}`,
        request: { method: ep.method, path: ep.path },
        response: { status: ep.statusCodes[0] ?? 200, body: {} },
    }));
    return JSON.stringify({
        consumer: { name: 'consumer' },
        provider: { name: title.replace(/\s+/g, '-').toLowerCase() },
        interactions,
        metadata: { pactSpecification: { version: '2.0.0' } },
    }, null, 2);
}
function buildTrpcContent(title) {
    const routerName = toSnake(title);
    return [
        `// tRPC router contract for: ${title}`,
        '// Generated by Planu SDD MCP Server',
        "import { router, publicProcedure } from '../trpc';",
        "import { z } from 'zod';",
        '',
        `export const ${routerName}Router = router({`,
        '  getAll: publicProcedure.query(async () => {',
        '    // TODO: implement',
        '    return [];',
        '  }),',
        '  getById: publicProcedure.input(z.object({ id: z.string() })).query(async ({ input }) => {',
        '    // TODO: implement',
        '    return { id: input.id };',
        '  }),',
        '  create: publicProcedure',
        '    .input(z.object({ /* TODO: add fields */ }))',
        '    .mutation(async () => {',
        '      // TODO: implement',
        "      return { id: 'new-id' };",
        '    }),',
        '});',
        '',
    ].join('\n');
}
// === Mock generation ===
/**
 * Generate API endpoint mocks for parallel frontend/backend development.
 */
export function generateMocksFromSpec(_specTitle, endpoints) {
    return endpoints.map((ep) => buildMockDefinition(ep));
}
function buildMockDefinition(ep) {
    const errorResponses = [
        { status: 400, body: { error: 'Bad Request', message: 'Invalid input provided' } },
        { status: 404, body: { error: 'Not Found', message: 'Resource not found' } },
        { status: 500, body: { error: 'Internal Server Error', message: 'Unexpected error' } },
    ];
    return {
        endpoint: ep.path,
        method: ep.method,
        sampleData: buildSampleData(ep),
        delayMs: 100,
        errorResponses,
    };
}
function buildSampleData(ep) {
    if (ep.responseSchema && Object.keys(ep.responseSchema).length > 0) {
        return ep.responseSchema;
    }
    return {
        id: 'sample-id-001',
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
        data: {},
    };
}
/**
 * Generate an MSW (Mock Service Worker) handler file from mock definitions.
 */
export function generateMockServerTemplate(mocks) {
    const handlers = mocks
        .map((mock) => {
        const method = mock.method.toLowerCase();
        const responseBody = JSON.stringify(mock.sampleData, null, 4).replace(/^/gm, '    ');
        return `  http.${method}('${mock.endpoint}', async () => {\n    await delay(${mock.delayMs});\n    return HttpResponse.json(\n${responseBody}\n    );\n  }),`;
    })
        .join('\n\n');
    return `// MSW mock handlers — generated by Planu SDD MCP Server\nimport { http, HttpResponse, delay } from 'msw';\n\nexport const handlers = [\n${handlers}\n];\n`;
}
// === Contract validation ===
/**
 * Validate that implemented endpoints comply with the generated contract.
 */
export function validateContractCompliance(implementedEndpoints, contract) {
    return contract.endpoints.map((ep) => {
        const key = `${ep.method}:${ep.path}`;
        const found = implementedEndpoints.includes(key);
        return {
            endpoint: key,
            compliant: found,
            issues: found ? [] : [`Endpoint ${ep.method} ${ep.path} not found in implementation`],
        };
    });
}
//# sourceMappingURL=test-contract-generator.js.map