// engine/feasibility-validator.ts — Requirement feasibility validation (SPEC-040)
// Pure function — no I/O. Evaluates a list of requirements and returns a FeasibilityReport.
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const DISCLAIMER = 'Based on patterns from similar projects. Adjust based on your specific context.';
const FEATURE_KEYWORDS = [
    'quiero',
    'debe',
    'should',
    'feature',
    'screen',
    'page',
    'module',
    'endpoint',
    'flow',
    'integration',
    'dashboard',
    'panel',
    'view',
    'form',
    'report',
    'notification',
    'alert',
    'widget',
];
const PERFORMANCE_KEYWORDS = [
    'ultra-fast',
    'ultra fast',
    '< 100ms',
    '<100ms',
    'high performance',
    'low latency',
    'sub-second',
    'instant',
    'real-time response',
];
const SECURITY_KEYWORDS = [
    'encrypted',
    'encryption',
    'highly secure',
    'compliance',
    'hipaa',
    'gdpr',
    'pci',
    'soc2',
    'zero-trust',
    'audit log',
    'audit trail',
];
const CHEAP_KEYWORDS = [
    'cheap',
    'zero cost',
    'free',
    'no cost',
    'minimal cost',
    'low cost',
    'budget',
    'affordable',
    'open source only',
];
const OFFLINE_KEYWORDS = ['offline', 'offline mode', 'no internet', 'works offline'];
const REALTIME_KEYWORDS = [
    'real-time sync',
    'realtime sync',
    'live sync',
    'instant sync',
    'real-time updates',
    'websocket sync',
    'live updates',
];
// ---------------------------------------------------------------------------
// Score weights
// ---------------------------------------------------------------------------
const SCORE_PENALTIES = {
    blocker: 25,
    warning: 10,
    suggestion: 5,
};
// ---------------------------------------------------------------------------
// Main export
// ---------------------------------------------------------------------------
/**
 * Validate whether a set of requirements is feasible given project context.
 * Returns a FeasibilityReport with scored issues and a viability flag.
 */
export function validateFeasibility(requirements, knowledge) {
    const issues = [];
    const contextUsed = [];
    const fullText = requirements.join(' ').toLowerCase();
    const teamSize = resolveTeamSize(knowledge, contextUsed);
    const featureCount = countFeatures(requirements);
    // Rule 1: Timeline / team size
    checkTimelineIssues(featureCount, teamSize, issues, contextUsed);
    // Rule 2: Performance paradox
    checkPerformanceParadox(fullText, issues);
    // Rule 3: Scope creep
    checkScopeCreep(requirements.length, issues);
    // Rule 4: Offline vs real-time contradiction
    checkOfflineRealtime(fullText, issues);
    // Score calculation
    let score = 100;
    for (const issue of issues) {
        score -= SCORE_PENALTIES[issue.severity];
    }
    score = Math.max(0, score);
    const viable = score >= 50;
    const summary = buildSummary(score, issues, viable);
    return { score, issues, viable, summary, contextUsed, disclaimer: DISCLAIMER };
}
// ---------------------------------------------------------------------------
// Rule implementations
// ---------------------------------------------------------------------------
function checkTimelineIssues(featureCount, teamSize, issues, contextUsed) {
    if (teamSize > 0) {
        contextUsed.push(`team_size=${teamSize}`);
    }
    contextUsed.push(`estimated_features=${featureCount}`);
    if (teamSize > 0 && teamSize < 3 && featureCount > 10) {
        issues.push({
            type: 'team_size',
            description: `A team of ${teamSize} person(s) handling ${featureCount} features is very ambitious. ` +
                'Small teams typically deliver 3-5 features per sprint.',
            severity: 'blocker',
            suggestedAlternative: 'Prioritize the 5 most critical features for the MVP. ' +
                'Defer the rest to a roadmap backlog after launch.',
        });
    }
    else if (featureCount > 20) {
        issues.push({
            type: 'timeline',
            description: `${featureCount} features detected in requirements without explicit team size information. ` +
                'This scope may require a much larger team or longer timeline than anticipated.',
            severity: 'warning',
            suggestedAlternative: 'Define a clear MVP with at most 8-10 features. ' +
                'Split remaining features into post-launch milestones.',
        });
    }
}
function checkPerformanceParadox(fullText, issues) {
    const hasPerf = PERFORMANCE_KEYWORDS.some((kw) => fullText.includes(kw));
    const hasSecurity = SECURITY_KEYWORDS.some((kw) => fullText.includes(kw));
    const hasCheap = CHEAP_KEYWORDS.some((kw) => fullText.includes(kw));
    if (hasPerf && hasSecurity && hasCheap) {
        issues.push({
            type: 'performance',
            description: 'Requirements simultaneously ask for ultra-high performance, strong security/compliance, ' +
                'and zero/minimal cost. These three constraints are fundamentally in tension.',
            severity: 'warning',
            suggestedAlternative: 'Prioritize: (1) security for regulated data, (2) performance for critical paths, ' +
                '(3) accept infrastructure cost as a business investment. ' +
                'Consider managed services to balance cost and compliance.',
        });
    }
}
function checkScopeCreep(requirementCount, issues) {
    if (requirementCount > 30) {
        issues.push({
            type: 'scope',
            description: `${requirementCount} individual requirement items detected. ` +
                'Large requirement lists often signal scope creep and make prioritization difficult.',
            severity: 'warning',
            suggestedAlternative: 'Group requirements into 5-7 epics. ' +
                'Define acceptance criteria per epic rather than per individual item. ' +
                "Use MoSCoW (Must/Should/Could/Won't) to categorize.",
        });
    }
}
function checkOfflineRealtime(fullText, issues) {
    const hasOffline = OFFLINE_KEYWORDS.some((kw) => fullText.includes(kw));
    const hasRealtime = REALTIME_KEYWORDS.some((kw) => fullText.includes(kw));
    if (hasOffline && hasRealtime) {
        issues.push({
            type: 'contradiction',
            description: 'Requirements mention both "offline mode" and "real-time sync". ' +
                'These are fundamentally contradictory — offline means no live connection.',
            severity: 'blocker',
            suggestedAlternative: 'Choose one primary mode: (a) offline-first with periodic sync when online, ' +
                'or (b) real-time with graceful degradation when offline (show cached data). ' +
                'Libraries like RxDB or WatermelonDB support conflict-free offline-first sync.',
        });
    }
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function resolveTeamSize(knowledge, contextUsed) {
    // Try to infer team size from apps count as a proxy
    const appsCount = knowledge.apps.length;
    if (appsCount > 0) {
        contextUsed.push(`apps_count=${appsCount}`);
    }
    // We cannot reliably know team size unless contributed — return 0 (unknown)
    return 0;
}
function countFeatures(requirements) {
    const text = requirements.join(' ').toLowerCase();
    const words = text.split(/\W+/);
    return words.filter((w) => FEATURE_KEYWORDS.includes(w)).length;
}
function buildSummary(score, issues, viable) {
    if (issues.length === 0) {
        return `Requirements look realistic. Feasibility score: ${score}/100.`;
    }
    const blockers = issues.filter((i) => i.severity === 'blocker').length;
    const warnings = issues.filter((i) => i.severity === 'warning').length;
    const parts = [`Feasibility score: ${score}/100.`];
    if (!viable) {
        parts.push('WARNING: Score below 50 — significant issues detected before continuing.');
    }
    if (blockers > 0) {
        parts.push(`${blockers} blocker(s) must be addressed.`);
    }
    if (warnings > 0) {
        parts.push(`${warnings} warning(s) to review.`);
    }
    return parts.join(' ');
}
//# sourceMappingURL=feasibility-validator.js.map