// src/engine/elicitation/question-generator.ts
// SPEC-163: Generates structured clarification questions for spec creation.
// SPEC-219: Questions loaded from src/config/elicitation-questions.json via ConfigLoader.
import { z } from 'zod';
import { ConfigLoader } from '../config-loader.js';
// ---------------------------------------------------------------------------
// SPEC-219: Elicitation question config schema
// ---------------------------------------------------------------------------
const ElicitationQuestionConfigSchema = z.object({
    id: z.string().describe('Unique question identifier (e.g. users, success, scope)'),
    category: z
        .enum(['scope', 'users', 'data', 'behavior', 'constraints', 'success'])
        .describe('Question category: scope, users, data, behavior, constraints, or success'),
    questionTemplate: z
        .string()
        .describe('Question text. Use {title} as placeholder for the feature title'),
    hint: z.string().optional().describe('Optional guidance hint shown to the user'),
    required: z.boolean().describe('Whether the question must be answered'),
    answerType: z
        .enum(['text', 'choice', 'yes-no'])
        .describe('Answer format: text, choice, or yes-no'),
    choices: z.array(z.string()).optional().describe('Available choices when answerType is "choice"'),
    condition: z
        .enum(['always', 'data', 'api'])
        .describe('When to include this question: always, data (needs DB/store context), or api (needs API context)'),
    conditionKeywords: z
        .array(z.string())
        .optional()
        .describe('Keywords in description that trigger conditional inclusion'),
});
const questionConfigLoader = new ConfigLoader('elicitation-questions', z.array(ElicitationQuestionConfigSchema));
/**
 * Resolve a question template against the feature title.
 */
function resolveTemplate(template, title) {
    return template.replace(/\{title\}/g, title);
}
/**
 * Determine whether a conditional question should be included.
 */
function shouldInclude(config, lowerDesc, context) {
    if (config.condition === 'always') {
        return true;
    }
    if (config.condition === 'data') {
        if (context?.hasDatabase === true) {
            return true;
        }
        return (config.conditionKeywords ?? []).some((kw) => lowerDesc.includes(kw));
    }
    // condition === 'api' is the only remaining case
    if (context?.isApi === true) {
        return true;
    }
    return (config.conditionKeywords ?? []).some((kw) => lowerDesc.includes(kw));
}
/** Generate standard clarification questions for a feature spec */
export function generateSpecQuestions(title, description, context) {
    const configs = questionConfigLoader.load();
    const lowerDesc = description.toLowerCase();
    const questions = [];
    for (const config of configs) {
        if (!shouldInclude(config, lowerDesc, context)) {
            continue;
        }
        const question = {
            id: config.id,
            category: config.category,
            question: resolveTemplate(config.questionTemplate, title),
            required: config.required,
            answerType: config.answerType,
        };
        if (config.hint !== undefined) {
            question.hint = config.hint;
        }
        if (config.choices !== undefined) {
            question.choices = config.choices;
        }
        questions.push(question);
    }
    return questions;
}
/** Format questions as a readable prompt for the LLM to present to the user */
export function formatQuestionsAsPrompt(session) {
    const lines = [
        `## Clarification needed for: "${session.title}"`,
        '',
        'Please answer the following questions to help create a detailed spec:',
        '',
    ];
    session.questions.forEach((q, i) => {
        const required = q.required ? ' *(required)*' : ' *(optional)*';
        lines.push(`**${i + 1}. ${q.question}**${required}`);
        if (q.hint !== undefined) {
            lines.push(`   > Hint: ${q.hint}`);
        }
        if (q.choices !== undefined) {
            lines.push('   Options:');
            q.choices.forEach((c) => lines.push(`   - ${c}`));
        }
        lines.push('');
    });
    lines.push('---');
    lines.push('*Reply with your answers (e.g., "1. Admin users 2. User sees dashboard with charts...")*');
    return lines.join('\n');
}
/** Parse answers from free-form text (numbered list format) */
export function parseAnswers(questions, answersText) {
    const answers = {};
    const lines = answersText.split('\n');
    lines.forEach((line) => {
        const match = /^(\d+)[.)]\s*(.+)/.exec(line.trim());
        if (match?.[1] !== undefined && match[2] !== undefined) {
            const idx = parseInt(match[1], 10) - 1;
            const question = questions[idx];
            if (idx >= 0 && question !== undefined) {
                answers[question.id] = match[2].trim();
            }
        }
    });
    return answers;
}
//# sourceMappingURL=question-generator.js.map