// engine/api-spec-generator/ac-builder.ts — Build Planu ACs from parsed API operations (SPEC-286)
// ---------------------------------------------------------------------------
// Pattern-based AC generators
// ---------------------------------------------------------------------------
function buildRequiredFieldACs(operation) {
    return operation.fields
        .filter((f) => f.required)
        .map((f) => ({
        text: `Debe retornar 400 si \`${f.name}\` no está presente`,
        source: 'required-field',
    }));
}
function buildEmailFormatACs(operation) {
    return operation.fields
        .filter((f) => f.format === 'email')
        .map((f) => ({
        text: `Debe validar formato de email en el campo \`${f.name}\``,
        source: 'email-format',
    }));
}
function isFrontendContext(target, tags) {
    if (target === 'frontend' || target === 'ios' || target === 'android') {
        return true;
    }
    const frontendTags = ['ui', 'storybook', 'design', 'component', 'frontend'];
    return tags?.some((t) => frontendTags.includes(t.toLowerCase())) ?? false;
}
function buildResponseCodeACs(operation, options) {
    const acs = [];
    const statusCodes = new Set(operation.responses.map((r) => r.statusCode));
    const isFrontend = isFrontendContext(options?.target, options?.tags);
    if (statusCodes.has(401) && !isFrontend) {
        acs.push({
            text: 'Debe retornar 401 si el token de autenticación es inválido o está ausente',
            source: 'response-code',
        });
    }
    if (statusCodes.has(403) && !isFrontend) {
        acs.push({
            text: 'Debe retornar 403 si el usuario no tiene permisos suficientes',
            source: 'response-code',
        });
    }
    if (statusCodes.has(404)) {
        acs.push({
            text: 'Debe retornar 404 si el recurso solicitado no existe',
            source: 'response-code',
        });
    }
    if (statusCodes.has(409)) {
        acs.push({
            text: 'Debe retornar 409 si hay conflicto con el estado actual del recurso',
            source: 'response-code',
        });
    }
    if (statusCodes.has(422)) {
        acs.push({
            text: 'Debe retornar 422 con detalles de validación cuando los datos son semánticamente inválidos',
            source: 'response-code',
        });
    }
    if (statusCodes.has(429) && !isFrontend) {
        acs.push({
            text: 'Debe implementar rate limiting y retornar 429 cuando se excede el límite',
            source: 'rate-limit',
        });
    }
    return acs;
}
function buildEnumFieldACs(operation) {
    return operation.fields
        .filter((f) => (f.enumValues ?? []).length > 0)
        .map((f) => ({
        text: `Debe rechazar valores inválidos en \`${f.name}\` — valores permitidos: ${(f.enumValues ?? []).join(', ')}`,
        source: 'pattern',
    }));
}
function buildHappyPathAC(operation) {
    const method = operation.method?.toLowerCase() ?? operation.operationType ?? 'execute';
    const resource = operation.resourceGroup;
    const actionLabel = {
        get: `retornar ${resource} correctamente`,
        post: `crear ${resource} y retornar 201 con el recurso creado`,
        put: `actualizar ${resource} y retornar 200`,
        patch: `actualizar parcialmente ${resource} y retornar 200`,
        delete: `eliminar ${resource} y retornar 204 o 200`,
        query: `retornar los datos de ${resource} correctamente`,
        mutation: `ejecutar la mutación en ${resource} y confirmar con el resultado`,
        subscription: `establecer la suscripción a ${resource} y recibir eventos`,
    };
    const action = actionLabel[method] ?? `procesar operación en ${resource}`;
    return {
        text: `Debe ${action} cuando los datos son válidos`,
        source: 'pattern',
    };
}
// ---------------------------------------------------------------------------
// Public builder
// ---------------------------------------------------------------------------
export function buildACs(operation, options) {
    const acs = [
        buildHappyPathAC(operation),
        ...buildRequiredFieldACs(operation),
        ...buildEmailFormatACs(operation),
        ...buildEnumFieldACs(operation),
        ...buildResponseCodeACs(operation, options),
    ];
    // Deduplicate by text
    const seen = new Set();
    return acs.filter((ac) => {
        if (seen.has(ac.text)) {
            return false;
        }
        seen.add(ac.text);
        return true;
    });
}
/** Format ACs as a markdown checklist string */
export function formatACsAsMarkdown(acs) {
    return acs.map((ac) => `- [ ] ${ac.text}`).join('\n');
}
//# sourceMappingURL=ac-builder.js.map