// src/engine/elicitation/answer-extractor.ts
// SPEC-624: Extracts pre-existing answers from description to suppress redundant questions.
const FRONTEND_TERMS = /\b(component|ui|page|css|style|layout|form|button|modal|dialog)\b/;
const BACKEND_TERMS = /\b(api|endpoint|route|handler|migration|query|rpc|action|middleware)\b/;
const INFRA_TERMS = /\b(deploy|ci|cd|docker|pipeline|config|env)\b/;
const BILLING_TERMS = /\b(payment|billing|invoice|subscription|checkout|pricing|pay)\b/;
const DATABASE_TERMS = /\b(database|schema|migration|table|query|sql|rls|rpc|persist|persistence|data access)\b/;
const ACTION_RE = /\b(add|build|create|fix|update|remove|delete|integrate|sync|import|export|approve|reject|upload|download|migrate|configure|validate)\b\s+(?:(?:a|an|the|new)\s+)?([a-z0-9][a-z0-9 -]{1,60})/i;
const ACTOR_TERMS = /\b(admin|administrator|manager|owner|customer|user|member|team|approver)\b/gi;
const DATA_OBJECT_TERMS = /\b(account|profile|request|invoice|subscription|payment|order|report|file|avatar|table|policy|record|settings)\b/gi;
const PERMISSION_TERMS = /\b(approval|approve|reject|admin|permission|role|rls|policy|access|auth|login|oauth|owner|manager)\b/;
const DESTRUCTIVE_TERMS = /\b(delete|remove|archive|discard|drop|truncate|revoke|reset)\b/;
const RISK_TERMS = /\b(approval|approve|payment|billing|auth|login|permission|role|delete|remove|migration|sync|webhook|external|api|rls|privacy|security)\b/gi;
const PAYMENT_PROVIDERS = [
    { name: 'Stripe', pattern: /\bstripe\b/ },
    { name: 'PayPal', pattern: /\bpaypal\b/ },
    { name: 'Paddle', pattern: /\bpaddle\b/ },
    { name: 'Braintree', pattern: /\bbraintree\b/ },
    { name: 'Square', pattern: /\bsquare\b/ },
    { name: 'Adyen', pattern: /\badyen\b/ },
];
/**
 * Scan a feature description for pre-existing answers.
 * Any signal set to true means the corresponding question can be suppressed.
 */
export function extractSignals(description) {
    const lower = stripIncidentalReferences(description.toLowerCase());
    const hasTarget = FRONTEND_TERMS.test(lower) || BACKEND_TERMS.test(lower) || INFRA_TERMS.test(lower);
    const hasDatabase = DATABASE_TERMS.test(lower);
    const hasUi = FRONTEND_TERMS.test(lower);
    let namedProvider = null;
    for (const { name, pattern } of PAYMENT_PROVIDERS) {
        if (pattern.test(lower)) {
            namedProvider = name;
            break;
        }
    }
    // hasBilling: billing/payment keywords OR a specific provider was named
    const hasBilling = BILLING_TERMS.test(lower) || namedProvider !== null;
    const wordCount = description.trim().split(/\s+/).length;
    const hasScope = wordCount >= 10;
    const actionMatch = ACTION_RE.exec(lower);
    const action = actionMatch?.[1] ?? null;
    const domainObject = cleanDomainObject(actionMatch?.[2] ?? null);
    const actors = uniqueMatches(lower, ACTOR_TERMS);
    const dataObjects = uniqueMatches(lower, DATA_OBJECT_TERMS);
    const riskTerms = uniqueMatches(lower, RISK_TERMS);
    const integrations = [
        ...PAYMENT_PROVIDERS.filter(({ pattern }) => pattern.test(lower)).map(({ name }) => name),
        ...extractExternalIntegrations(lower),
    ];
    const hasPermissionRisk = PERMISSION_TERMS.test(lower);
    const hasDestructiveAction = DESTRUCTIVE_TERMS.test(lower);
    return {
        hasTarget,
        hasBilling,
        hasDatabase,
        hasUi,
        namedProvider,
        hasScope,
        action,
        domainObject,
        actors,
        integrations,
        dataObjects,
        hasPermissionRisk,
        hasDestructiveAction,
        riskTerms,
    };
}
function stripIncidentalReferences(description) {
    return description
        .replace(/`[^`]*(?:\/|\.\w{1,8})[^`]*`/g, ' ')
        .replace(/\b\S+\/\S+\b/g, ' ')
        .replace(/\b[\w-]+\.(?:ts|tsx|js|jsx|mjs|cjs|json|md|css|scss|py|go|rs|java|rb|php)\b/g, ' ');
}
function cleanDomainObject(value) {
    if (value === null) {
        return null;
    }
    const cleaned = value
        .replace(/\b(that|with|to|from|when|where|and|or|but|using|in)\b.*$/i, '')
        .replace(/\s+/g, ' ')
        .trim();
    return cleaned.length > 0 ? cleaned : null;
}
function uniqueMatches(text, pattern) {
    const flags = pattern.flags.includes('g') ? pattern.flags : `${pattern.flags}g`;
    const globalPattern = new RegExp(pattern.source, flags);
    return Array.from(new Set(Array.from(text.matchAll(globalPattern)).map((match) => match[0])));
}
function extractExternalIntegrations(text) {
    const matches = text.match(/\b([a-z][a-z0-9-]+)\s+(?:api|webhook|sdk|integration)\b/gi) ?? [];
    return Array.from(new Set(matches.map((match) => match.replace(/\s+(api|webhook|sdk|integration)$/i, ''))));
}
//# sourceMappingURL=answer-extractor.js.map