import { elicitOrFallback, buildEnumSchema } from '../engine/elicitation/elicit-helper.js';
import { scoreAmbiguity, shouldBlock } from '../engine/ambiguity-detector.js';
import { setFocus, getFocus, checkFocusDrift, parseChangeFocusDirective, } from '../engine/focus-tracker.js';
import { getParadigmRecommendations, formatParadigmObservations, } from '../engine/paradigm-advisor.js';
import { classifyIntent } from '../engine/facilitate/intent-classifier.js';
import { loadContext } from '../engine/facilitate/context-loader.js';
import { route } from '../engine/facilitate/router.js';
import { parsePlanContent } from '../engine/facilitate/plan-parser.js';
import { compactJson, compactResult, compactError } from './output-formatter.js';
import { interactiveResult } from './response-helpers.js';
import { resolveNewProjectOnboarding } from '../engine/onboarding/new-project-resolver.js';
// ---------------------------------------------------------------------------
// Scenario detection (SPEC-037 legacy — kept for backward compatibility)
// ---------------------------------------------------------------------------
function detectScenario(description) {
    const lower = description.toLowerCase();
    if (lower.includes('how to') ||
        lower.includes('how do i') ||
        lower.includes('what tool') ||
        lower.includes('i need help with') ||
        lower.includes('fix') ||
        lower.includes('error') ||
        lower.includes('problem')) {
        return 'concrete_problem';
    }
    if (lower.includes('already have') ||
        lower.includes('my project') ||
        lower.includes('our project') ||
        /existing project/i.test(description) ||
        lower.includes('/')) {
        return 'existing_project';
    }
    return 'new_project';
}
// ---------------------------------------------------------------------------
// Existing project scenario
// ---------------------------------------------------------------------------
function buildExistingProjectResponse(description) {
    return (`I'll run a diagnostic on your project.\n\n` +
        `Please provide the project path and call:\n` +
        `- \`init_project\` with your project path (if not yet initialized)\n` +
        `- \`reverse_engineer\` to analyze the codebase\n` +
        `- \`audit\` to check spec health\n\n` +
        `Request received: "${description.slice(0, 120)}"`);
}
// ---------------------------------------------------------------------------
// Concrete problem scenario
// ---------------------------------------------------------------------------
const PROBLEM_TO_TOOL = [
    [/verif|verificar|check.?spec/i, 'validate', 'validate a spec'],
    [/validat/i, 'validate', 'validate a spec'],
    [/spec|user stor/i, 'create_spec', 'create a spec/user story'],
    [/estimat/i, 'estimate', 'estimate effort and cost'],
    [/test/i, 'generate_tests', 'generate tests'],
    [/document|doc/i, 'generate_docs', 'generate documentation'],
    [/drift|diverge/i, 'detect_drift', 'detect spec drift'],
    [/schema|database|db/i, 'design_schema', 'design a database schema'],
    [/ui|interface|screen/i, 'define_ui_contract', 'define a UI contract'],
    [/execution|plan|roadmap/i, 'generate_execution_plan', 'generate an execution plan'],
    [/checklist/i, 'generate_checklist', 'generate a checklist'],
];
function buildConcreteProblemResponse(description) {
    const match = PROBLEM_TO_TOOL.find(([re]) => re.test(description));
    if (match) {
        const [, tool, action] = match;
        return (`It sounds like you want to ${action}.\n\n` +
            `Recommended tool: \`${tool}\`\n\n` +
            `Call \`${tool}\` with your project ID and the relevant parameters.`);
    }
    return (`I can help with that! Here are the most relevant Planu tools:\n\n` +
        `- \`create_spec\` — write a new user story / spec\n` +
        `- \`clarify_requirements\` — clarify vague requirements\n` +
        `- \`estimate\` — estimate effort and cost\n` +
        `- \`validate\` — check if a spec is complete\n` +
        `- \`generate_tests\` — generate test scaffolds\n\n` +
        `What specifically would you like to do?`);
}
// ---------------------------------------------------------------------------
// Paradigm observations (SPEC-035b)
// ---------------------------------------------------------------------------
export function buildParadigmObservations(paradigmReport) {
    if (!paradigmReport) {
        return '';
    }
    const recommendations = getParadigmRecommendations(paradigmReport);
    return formatParadigmObservations(recommendations, null);
}
// ---------------------------------------------------------------------------
// Expert observations generator
// ---------------------------------------------------------------------------
function generateExpertObservations(description) {
    const observations = [];
    const lower = description.toLowerCase();
    if (/fast|quick|instant|real.?time/i.test(description)) {
        observations.push({
            type: 'metric',
            text: 'Vague performance requirement detected ("fast", "quick"). Consider specifying concrete SLOs.',
            action: 'Add: "Response time < 200ms at p95 under 1000 concurrent users"',
        });
    }
    if (/payment|stripe|credit card|billing/i.test(description)) {
        observations.push({
            type: 'risk',
            text: 'Payment handling requires PCI-DSS compliance consideration.',
            action: 'Use a certified payment processor (Stripe, Braintree) — never store raw card data.',
        });
    }
    if (/auth|login|password|jwt/i.test(description) && !lower.includes('oauth')) {
        observations.push({
            type: 'suggestion',
            text: 'Consider OAuth2/OIDC instead of custom auth to reduce security risk.',
            action: 'Evaluate Auth0, Clerk, or Supabase Auth before building from scratch.',
        });
    }
    if (/microservice/i.test(description)) {
        observations.push({
            type: 'risk',
            text: 'Microservices add operational complexity. Ensure you need them before committing.',
            action: 'Start with a modular monolith and extract services when load justifies it.',
        });
    }
    return observations;
}
// ---------------------------------------------------------------------------
// SPEC-264: Routing suggestion text
// ---------------------------------------------------------------------------
function buildRoutingSuggestion(decision) {
    switch (decision.action) {
        case 'resume':
            return `Resume work on spec ${decision.specId} — it matches your request and is in progress.`;
        case 'create-spec':
            return `Create a new spec for this ${decision.type} request using \`create_spec\`.`;
        case 'direct':
            return decision.reason;
        case 'clarify':
            return decision.question;
    }
}
// ---------------------------------------------------------------------------
// SPEC-264: Smart orchestrator path
// ---------------------------------------------------------------------------
async function runSmartOrchestrator(description, projectId, planContent) {
    // 1. Classify intent
    const intent = classifyIntent(description);
    // 2. Load context from project data
    const projectPath = projectId ?? process.cwd();
    const ctx = await loadContext(projectPath, intent.keywords);
    // 3. Handle Plan Mode content
    let parsedPlan = null;
    let effectiveDescription = description;
    if (planContent) {
        parsedPlan = parsePlanContent(planContent);
        if (parsedPlan) {
            effectiveDescription =
                `${parsedPlan.title}: ` + parsedPlan.acceptanceCriteria.slice(0, 3).join('; ');
        }
    }
    // 4. Route
    const decision = route(intent, ctx, effectiveDescription);
    // 5. Build compact response (≤150 tokens main content)
    const result = {
        action: 'facilitate',
        routing: decision,
        context: {
            activeCount: ctx.activeSpecs.length,
            relatedFound: ctx.relatedSpecs.map((s) => s.id),
        },
        intent: {
            type: intent.type,
            complexity: intent.complexity,
            confidence: intent.confidence,
        },
        suggestion: buildRoutingSuggestion(decision),
    };
    if (parsedPlan) {
        result.parsedPlan = {
            title: parsedPlan.title,
            acCount: parsedPlan.acceptanceCriteria.length,
            estimatedComplexity: parsedPlan.estimatedComplexity,
        };
    }
    return result;
}
// ---------------------------------------------------------------------------
// Main handler
// ---------------------------------------------------------------------------
export async function handleFacilitate(params, server) {
    const { description, projectId, sessionId, scenario: explicitScenario, step = 0, targetTool, checkFocus = false, changeFocus, paradigmReport, planContent, } = params;
    const sessionKey = sessionId ?? projectId ?? 'default';
    // SPEC-264: When planContent provided OR no explicit scenario/control params given,
    // use the smart orchestrator path.
    const useSmartOrchestrator = planContent !== undefined ||
        (explicitScenario === undefined &&
            targetTool === undefined &&
            !checkFocus &&
            changeFocus === undefined);
    if (useSmartOrchestrator) {
        try {
            const orchestratorResult = await runSmartOrchestrator(description, projectId, planContent);
            const observations = generateExpertObservations(description);
            const paradigmObs = buildParadigmObservations(paradigmReport);
            const merged = { ...orchestratorResult };
            if (observations.length > 0) {
                merged.expertObservations = observations;
            }
            if (paradigmObs) {
                merged.paradigmObservations = paradigmObs;
            }
            return ok(merged);
        }
        catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            return ok({ action: 'facilitate', error: message, fallback: true });
        }
    }
    try {
        // --- Focus change directive ---
        const changeFocusText = changeFocus ?? parseChangeFocusDirective(description);
        if (changeFocusText) {
            const newFocus = {
                objective: changeFocusText,
                associatedTool: targetTool,
                startedAt: new Date().toISOString(),
            };
            setFocus(sessionKey, newFocus);
            return ok({
                action: 'focus_updated',
                objective: changeFocusText,
                message: `Focus updated to: "${changeFocusText}". All subsequent requests will be evaluated against this objective.`,
            });
        }
        // --- Focus drift check ---
        if (checkFocus) {
            const shift = checkFocusDrift(sessionKey, description, targetTool);
            if (shift) {
                return ok({
                    action: 'focus_drift_detected',
                    shift,
                    message: shift.redirectMessage,
                    allowProceed: true,
                });
            }
            return ok({
                action: 'focus_aligned',
                currentFocus: getFocus(sessionKey),
                message: 'Request is aligned with the current session focus.',
            });
        }
        // --- Ambiguity check for a specific tool ---
        if (targetTool) {
            const ambiguity = scoreAmbiguity(description);
            const blocked = shouldBlock(targetTool, ambiguity);
            if (blocked) {
                // SPEC-595: Elicit the clarifying answer directly when client supports it
                if (server !== undefined && ambiguity.clarificationQuestion) {
                    const { field, property } = buildEnumSchema('dimension', ['yes', 'no', 'unsure', 'explain-more', 'cancel'], [
                        'Yes — proceed',
                        'No — do not proceed',
                        'Unsure — need more context',
                        'Explain in more detail',
                        'Cancel',
                    ], ambiguity.clarificationQuestion);
                    const schema = { type: 'object', properties: { [field]: property } };
                    const fallback = {
                        header: 'Clarify',
                        question: ambiguity.clarificationQuestion,
                        multiSelect: false,
                        options: [
                            { label: 'yes', description: 'Yes — proceed' },
                            { label: 'no', description: 'No — do not proceed' },
                            { label: 'unsure', description: 'Unsure — need more context' },
                            { label: 'explain-more', description: 'Explain in more detail' },
                            { label: 'cancel', description: 'Cancel' },
                        ],
                    };
                    const outcome = await elicitOrFallback(server, ambiguity.clarificationQuestion, schema, [
                        fallback,
                    ]);
                    if (outcome.mode === 'fallback') {
                        return {
                            content: [
                                {
                                    type: 'text',
                                    text: `⚡ INTERACTIVE — call AskUserQuestion now with the interactiveQuestions from structuredContent`,
                                },
                            ],
                            structuredContent: {
                                action: 'ambiguity_block',
                                level: ambiguity.level,
                                question: ambiguity.clarificationQuestion,
                                interactiveQuestions: outcome.interactiveQuestions,
                            },
                        };
                    }
                    const answer = outcome.action === 'accept'
                        ? (outcome.content?.dimension ?? 'unsure')
                        : 'cancel';
                    return ok({
                        action: 'ambiguity_resolved',
                        level: ambiguity.level,
                        blockingDimension: ambiguity.blockingDimension,
                        elicitedAnswer: answer,
                        message: answer === 'cancel'
                            ? 'Clarification cancelled.'
                            : `Dimension clarified: ${answer}. Proceed with \`${targetTool}\` as appropriate.`,
                    });
                }
                return ok({
                    action: 'ambiguity_block',
                    level: ambiguity.level,
                    score: ambiguity.score,
                    blockingDimension: ambiguity.blockingDimension,
                    question: ambiguity.clarificationQuestion,
                    message: `Before calling \`${targetTool}\`, please answer: ${ambiguity.clarificationQuestion}`,
                });
            }
            return ok({
                action: 'ambiguity_clear',
                level: ambiguity.level,
                score: ambiguity.score,
                message: `Request is clear enough for \`${targetTool}\`. Proceed.`,
            });
        }
        // --- Main facilitate flow (legacy scenario-based) ---
        const scenario = explicitScenario ?? detectScenario(description);
        const existingFocus = getFocus(sessionKey);
        if (!existingFocus) {
            setFocus(sessionKey, {
                objective: description,
                startedAt: new Date().toISOString(),
            });
        }
        const observations = generateExpertObservations(description);
        let guidance;
        switch (scenario) {
            case 'new_project': {
                const resolution = await resolveNewProjectOnboarding({
                    description,
                    parentWorkspacePath: params.parentWorkspacePath,
                    projectPath: params.projectId,
                    appName: params.appName,
                    appSlug: params.appSlug,
                    projectType: params.projectType,
                    platform: params.platform,
                    language: params.language,
                    framework: params.framework,
                    database: params.database,
                    createDirectory: params.createDirectory,
                    clarificationAnswers: params.clarificationAnswers,
                });
                if (!resolution.ready) {
                    const response = interactiveResult(resolution.questions, 'New project onboarding needs a target app folder and technology choices before Planu can initialize anything. Do not call init_project on the parent workspace yet.', 'universal');
                    response.structuredContent = {
                        ...response.structuredContent,
                        mode: 'new_project',
                        parentWorkspacePath: resolution.parentWorkspacePath,
                        resolvedProjectPath: resolution.resolvedProjectPath,
                        appSlug: resolution.appSlug,
                        errors: resolution.errors,
                        nextAction: 'Ask the user these questions, then call facilitate again with clarificationAnswers or explicit fields. Only call init_project with the resolved child projectPath.',
                    };
                    return response;
                }
                return ok({
                    action: 'facilitate',
                    scenario,
                    mode: 'new_project',
                    readyToInitialize: true,
                    resolvedProjectPath: resolution.resolvedProjectPath,
                    technologySelectionContract: resolution.contract,
                    nextAction: 'Call init_project with mode="new_project", projectPath set to resolvedProjectPath, createDirectory=true, and technologySelectionContract from this response.',
                });
            }
            case 'existing_project':
                guidance = buildExistingProjectResponse(description);
                break;
            case 'concrete_problem':
                guidance = buildConcreteProblemResponse(description);
                break;
        }
        const legacyResult = {
            action: 'facilitate',
            scenario,
            step,
            guidance,
        };
        if (observations.length > 0) {
            legacyResult.expertObservations = observations;
            legacyResult.expertNote = 'Expert observations added below — these do not block execution.';
        }
        const paradigmObservations = buildParadigmObservations(paradigmReport);
        if (paradigmObservations) {
            legacyResult.paradigmObservations = paradigmObservations;
        }
        return ok(legacyResult);
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return compactError(message);
    }
}
function ok(data) {
    return compactResult(compactJson(data, 200));
}
//# sourceMappingURL=facilitate.js.map