// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// tools/clarify-requirements/multiple-choice.ts — SPEC-337
// Structured multiple-choice options for clarify_requirements interview mode.
// Provides: per-question options[], stack detection, suggestedDescription builder.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
const OPTIONS_CATALOG = {
    stack_frontend: [
        'Next.js',
        'Remix',
        'Nuxt',
        'SvelteKit',
        'Astro',
        'Vite + React',
        'Angular',
        'Other: ___',
    ],
    stack_backend: [
        'Express',
        'Fastify',
        'NestJS',
        'Hono',
        'FastAPI',
        'Django',
        'Spring Boot',
        'Other: ___',
    ],
    stack_database: [
        'PostgreSQL',
        'MySQL',
        'SQLite',
        'MongoDB',
        'Redis',
        'Supabase',
        'PlanetScale',
        'Other: ___',
    ],
    stack_language: ['TypeScript', 'JavaScript', 'Python', 'Go', 'Java', 'Rust', 'Other: ___'],
    auth_method: [
        'Email + password',
        'Google OAuth',
        'GitHub OAuth',
        'Magic link',
        'JWT (custom)',
        'Session-based',
        'API key',
        'Other: ___',
    ],
    scope_type: ['New feature', 'Improvement to existing', 'Bug fix', 'Refactor', 'Other: ___'],
    user_type: ['End user', 'Admin', 'Developer / internal', 'All users', 'Other: ___'],
    mvp_scope: [
        'Core happy path only',
        'Happy path + error handling',
        'Full feature with edge cases',
        'MVP first, iterate later',
        'Other: ___',
    ],
    performance_target: [
        '< 100ms (real-time)',
        '< 500ms (interactive)',
        '< 2s (acceptable)',
        'No strict SLA',
        'Other: ___',
    ],
    ui_mockup: [
        'Yes, Figma mockup available',
        'Rough sketch only',
        'No mockup — describe in text',
        'Other: ___',
    ],
    login_method: [
        'Email/password',
        'Google',
        'Apple',
        'Magic link',
        'GitHub',
        'SSO / SAML',
        'Other: ___',
    ],
};
/**
 * Detect the project stack by reading package.json and/or requirements.txt
 * from the given project path.
 */
export async function detectStack(projectPath) {
    const result = {
        framework: null,
        language: null,
        database: null,
        detectedLibs: [],
    };
    try {
        const pkgRaw = await readFile(join(projectPath, 'package.json'), 'utf-8');
        const pkg = JSON.parse(pkgRaw);
        const allDeps = {
            ...(pkg.dependencies ?? {}),
            ...(pkg.devDependencies ?? {}),
        };
        const libs = Object.keys(allDeps);
        result.detectedLibs = libs;
        // Framework detection
        if (libs.includes('next')) {
            result.framework = 'Next.js';
        }
        else if (libs.includes('@remix-run/react') || libs.includes('@remix-run/node')) {
            result.framework = 'Remix';
        }
        else if (libs.includes('nuxt')) {
            result.framework = 'Nuxt';
        }
        else if (libs.includes('@sveltejs/kit')) {
            result.framework = 'SvelteKit';
        }
        else if (libs.includes('astro')) {
            result.framework = 'Astro';
        }
        else if (libs.includes('fastify')) {
            result.framework = 'Fastify';
        }
        else if (libs.includes('@nestjs/core')) {
            result.framework = 'NestJS';
        }
        else if (libs.includes('express')) {
            result.framework = 'Express';
        }
        else if (libs.includes('hono')) {
            result.framework = 'Hono';
        }
        // Language (TypeScript presence)
        if (libs.includes('typescript') || libs.includes('ts-node') || libs.includes('tsx')) {
            result.language = 'TypeScript';
        }
        else {
            result.language = 'JavaScript';
        }
        // Database detection
        if (libs.includes('pg') || libs.includes('postgres')) {
            result.database = 'PostgreSQL';
        }
        else if (libs.includes('mysql2') || libs.includes('mysql')) {
            result.database = 'MySQL';
        }
        else if (libs.includes('better-sqlite3') || libs.includes('sqlite3')) {
            result.database = 'SQLite';
        }
        else if (libs.includes('mongoose') || libs.includes('mongodb')) {
            result.database = 'MongoDB';
        }
        else if (libs.includes('@supabase/supabase-js')) {
            result.database = 'Supabase';
        }
        else if (libs.includes('ioredis') || libs.includes('redis')) {
            result.database = 'Redis';
        }
    }
    catch {
        // No package.json — try requirements.txt for Python
        try {
            const reqRaw = await readFile(join(projectPath, 'requirements.txt'), 'utf-8');
            const lines = reqRaw
                .split('\n')
                .map((l) => (l.split('=')[0] ?? l).split('>')[0]?.split('<')[0]?.trim().toLowerCase() ?? '');
            result.detectedLibs = lines.filter(Boolean);
            if (lines.includes('django') || lines.includes('django-rest-framework')) {
                result.framework = 'Django';
                result.language = 'Python';
            }
            else if (lines.includes('fastapi')) {
                result.framework = 'FastAPI';
                result.language = 'Python';
            }
            else if (lines.includes('flask')) {
                result.framework = 'Flask';
                result.language = 'Python';
            }
            else {
                result.language = 'Python';
            }
            if (lines.includes('psycopg2') || lines.includes('psycopg2-binary')) {
                result.database = 'PostgreSQL';
            }
            else if (lines.includes('pymysql') || lines.includes('mysql-connector-python')) {
                result.database = 'MySQL';
            }
            else if (lines.includes('motor') || lines.includes('pymongo')) {
                result.database = 'MongoDB';
            }
        }
        catch {
            // No manifest files found — detection yields nulls
        }
    }
    return result;
}
/**
 * Returns true if the question should be skipped because the stack already
 * provides a definitive answer.
 */
export function shouldSkipQuestion(question, stack) {
    const lower = question.question.toLowerCase();
    if ((lower.includes('stack') || lower.includes('framework') || lower.includes('language')) &&
        (stack.framework !== null || stack.language !== null)) {
        return true;
    }
    if (lower.includes('database') && stack.database !== null) {
        return true;
    }
    return false;
}
/**
 * Resolves option list from a catalog key.
 */
function resolveOptions(key) {
    return OPTIONS_CATALOG[key];
}
/**
 * Attaches structured `options[]` to a question based on its content.
 * Each question gets 3-8 concrete choices + 'Other: ___' fallback.
 */
export function attachOptions(question) {
    const lower = question.question.toLowerCase();
    let options;
    if (lower.includes('login') || lower.includes('sign in') || lower.includes('sign up')) {
        options = resolveOptions('login_method');
    }
    else if (lower.includes('auth')) {
        options = resolveOptions('auth_method');
    }
    else if (lower.includes('frontend') || lower.includes('ui framework')) {
        options = resolveOptions('stack_frontend');
    }
    else if (lower.includes('backend') || lower.includes('server framework')) {
        options = resolveOptions('stack_backend');
    }
    else if (lower.includes('database') || lower.includes('db')) {
        options = resolveOptions('stack_database');
    }
    else if (lower.includes('stack') || lower.includes('framework') || lower.includes('language')) {
        options = resolveOptions('stack_language');
    }
    else if (lower.includes('new feature') ||
        lower.includes('improvement') ||
        lower.includes('feature or')) {
        options = resolveOptions('scope_type');
    }
    else if (lower.includes('user') &&
        (lower.includes('who') || lower.includes('primary') || lower.includes('persona'))) {
        options = resolveOptions('user_type');
    }
    else if (lower.includes('must-have') ||
        lower.includes('minimum viable') ||
        lower.includes('mvp') ||
        lower.includes('first version')) {
        options = resolveOptions('mvp_scope');
    }
    else if (lower.includes('performance') ||
        lower.includes('response time') ||
        lower.includes('latency')) {
        options = resolveOptions('performance_target');
    }
    else if (lower.includes('mockup') ||
        lower.includes('design') ||
        lower.includes('reference design')) {
        options = resolveOptions('ui_mockup');
    }
    else if (lower.includes('scope') && lower.includes('done')) {
        options = resolveOptions('mvp_scope');
    }
    if (options === undefined) {
        return question;
    }
    return { ...question, options };
}
/**
 * Builds a `suggestedDescription` string from accumulated answers.
 * The returned string is suitable for passing directly to create_spec.
 */
export function buildSuggestedDescription(topic, answers, questions) {
    const parts = [`Feature: ${topic}.`];
    for (const q of questions) {
        const answer = answers[q.id];
        if (answer === undefined || answer.trim() === '') {
            continue;
        }
        const trimmedAnswer = answer.trim();
        const shortQuestion = q.question
            .replace(/^(What|Who|Is|Are|Does|Do|How|Which)\s+/i, '')
            .replace(/\?$/, '');
        parts.push(`${shortQuestion}: ${trimmedAnswer}.`);
    }
    return parts.join(' ');
}
//# sourceMappingURL=multiple-choice.js.map