import { t } from '../../i18n/index.js';
import { formatSuccess, addNextSteps } from '../response-helpers.js';
import { buildNextAction, buildLifecycleMap } from '../../engine/lifecycle-hints.js';
import { buildUpdateStatusSummary } from '../../engine/human-summary.js';
// ---------------------------------------------------------------------------
// SPEC-721: Validate gate blocked response builder
// ---------------------------------------------------------------------------
const REASON_TO_FIX_HINT = {
    validate_score_below_threshold: 'Reach 100/100 validation coverage for the spec, then retry. Or use forceStatus:true + forceStatusReason (≥100 chars).',
    validate_gate_no_criteria: 'Add `scenarios:` to the spec frontmatter (BDD format), or use check_readiness to inject ' +
        'criteria, then retry. Or use forceStatus:true + forceStatusReason (≥100 chars).',
    validate_gate_crash: 'The validate engine crashed. Inspect logs, fix the spec or engine, and retry. ' +
        'If you are sure the implementation is complete, use forceStatus:true with a reason (≥100 chars).',
    validate_gate_timeout: 'The validate engine took longer than the allowed budget — likely a project size or external-call issue. ' +
        'Investigate or use forceStatus:true with a reason (≥100 chars).',
    validate_gate_unreachable: 'forceStatus must be accompanied by forceStatusReason (string ≥ 100 characters).',
};
/**
 * SPEC-721: Build a ToolResult that blocks a `done` transition because
 * `runValidateGate` returned `blocked: true`.
 */
export function buildValidateBlockedResponse(specId, result) {
    const scoreStr = result.score !== null ? `${String(result.score)}/100` : 'null';
    const errorLine = result.errorMessage ? `\n  Detail: ${result.errorMessage}` : '';
    const fixHint = REASON_TO_FIX_HINT[result.reason];
    return {
        isError: true,
        content: [
            {
                type: 'text',
                text: `❌ Validate gate blocked transition for ${specId}.\n` +
                    `  Reason: ${result.reason}\n` +
                    `  Score: ${scoreStr}${errorLine}\n` +
                    `  Fix hint: ${fixHint}`,
            },
        ],
        structuredContent: {
            error: 'validate_gate_blocked',
            reason: result.reason,
            score: result.score,
            errorMessage: result.errorMessage ?? null,
            fixHint,
        },
    };
}
// ---------------------------------------------------------------------------
// SPEC-731: Dry-run response builder
// ---------------------------------------------------------------------------
/**
 * Build a ToolResult for a dry-run evaluation.
 * Mirrors the shape of a success response but with dryRun: true discriminator.
 */
export function buildDryRunResponse(dryRunResult) {
    const statusIcon = dryRunResult.wouldTransition ? '✅' : '❌';
    const gateLines = Object.entries(dryRunResult.gates)
        .map(([gate, outcome]) => `  - ${gate}: ${outcome}`)
        .join('\n');
    const blockLines = dryRunResult.blockingReasons.length > 0
        ? `\n\n**Blocking reasons:**\n${dryRunResult.blockingReasons.map((r) => `- ${r}`).join('\n')}`
        : '';
    return {
        content: [
            {
                type: 'text',
                text: `${statusIcon} **Dry-run preview** — no writes occurred.\n\n` +
                    `Would transition: **${dryRunResult.wouldTransition ? 'YES' : 'NO'}**\n\n` +
                    `**Gate outcomes:**\n${gateLines}${blockLines}`,
            },
        ],
        structuredContent: dryRunResult,
    };
}
export const STATUS_EMOJIS = {
    draft: '📝',
    review: '🔍',
    approved: '✅',
    implementing: '⚙️',
    done: '🎉',
    discarded: '🗑️',
};
// eslint-disable-next-line complexity -- aggregates many host- and status-specific branches
export function buildStatusResponse(result, specId, currentStatus, newStatus, reconciliationMarkdown, recordActualHint, specTitle, shellHygieneHint) {
    const fromEmoji = STATUS_EMOJIS[currentStatus];
    const toEmoji = STATUS_EMOJIS[newStatus];
    const r = result;
    const lines = [
        `**SPEC-${specId}** moved: ${fromEmoji} \`${currentStatus}\` → ${toEmoji} \`${newStatus}\``,
    ];
    if (r.autoBranch) {
        lines.push(`\n🌿 Branch created: \`${r.autoBranch}\``);
    }
    if (r.protectedBranchWarning) {
        lines.push(`\n⚠️ ${r.protectedBranchWarning}`);
    }
    if (r.mergeWarning) {
        lines.push(`\n⚠️ ${r.mergeWarning}`);
    }
    if (r.validationWarning) {
        lines.push(`\n⚠️ ${r.validationWarning}`);
    }
    if (r.prSuggestion) {
        lines.push(`\n🔗 ${r.prSuggestion.title}`);
    }
    if (r.metrics) {
        lines.push(`\n📊 Accuracy: ${Math.round(r.metrics.accuracyScore * 100)}% | ` +
            `Estimated: ${String(r.metrics.estimatedHours)}h → Actual: ${String(r.metrics.actualHours)}h`);
    }
    if (r.actuals && (r.actuals.tokensOpus > 0 || r.actuals.tokensSonnet > 0)) {
        const prefix = r.actuals.estimated ? '~' : '';
        const opus = r.actuals.tokensOpus > 0 ? `${prefix}${r.actuals.tokensOpus.toLocaleString()} opus` : null;
        const sonnet = r.actuals.tokensSonnet > 0
            ? `${prefix}${r.actuals.tokensSonnet.toLocaleString()} sonnet`
            : null;
        const tokenStr = [opus, sonnet].filter(Boolean).join(' + ');
        const costStr = r.actuals.apiCostUsd > 0 ? ` | ${prefix}$${r.actuals.apiCostUsd.toFixed(3)} API` : '';
        lines.push(`\n🤖 Tokens: ${tokenStr}${costStr}${r.actuals.estimated ? ' *(auto-estimated)*' : ''}`);
    }
    if (r.validateScore !== null && r.validateScore !== undefined) {
        lines.push(`\n✅ Validate score: ${String(r.validateScore)}/100`);
    }
    if (r.cascade.affectedSpecs.length > 0) {
        lines.push(`\n🔗 Downstream specs affected: ${r.cascade.affectedSpecs.map((s) => `SPEC-${s}`).join(', ')}`);
    }
    if (r.codeRealityWarning) {
        lines.push(`\n${r.codeRealityWarning}`);
    }
    if (r.crashShieldWarning) {
        lines.push(`\n${r.crashShieldWarning}`);
    }
    if (r.forcedBypassWarning) {
        lines.push(`\n🚨 **FORCE BYPASS**: ${r.forcedBypassWarning}`);
    }
    if (r.constitutionWarnings && r.constitutionWarnings.length > 0) {
        lines.push(`\n⚠️ **Constitution Warnings**\n${r.constitutionWarnings.map((w) => `- ${w.description}`).join('\n')}`);
    }
    if (r.conventionWarnings && r.conventionWarnings.length > 0) {
        lines.push(`\n⚠️ **Convention Violations**\n${r.conventionWarnings.map((w) => `- ${w}`).join('\n')}`);
    }
    if (r.compileWarnings && r.compileWarnings.length > 0) {
        lines.push(`\n⚠️ **Compile Warnings**\n${r.compileWarnings.map((w) => `- ${w}`).join('\n')}`);
    }
    if (r.lintWarnings && r.lintWarnings.length > 0) {
        lines.push(`\n⚠️ **Lint Warnings**\n${r.lintWarnings.map((w) => `- ${w}`).join('\n')}`);
    }
    if (r.testWarnings && r.testWarnings.length > 0) {
        lines.push(`\n⚠️ **Test Warnings**\n${r.testWarnings.map((w) => `- ${w}`).join('\n')}`);
    }
    // SPEC-698: Frontmatter sync warnings — make stale spec.md visible to the user
    if (r.frontmatterSyncWarnings && r.frontmatterSyncWarnings.length > 0) {
        for (const w of r.frontmatterSyncWarnings) {
            const target = w.specPath ?? '<unknown path>';
            lines.push(`\n⚠ frontmatter sync failed for ${w.specId} at ${target}: ${w.reason}`);
        }
        lines.push('\n💡 Run `repair_frontmatter_drift` to reconcile the on-disk frontmatter.');
    }
    // SPEC-447: Compliance gate result
    if (r.complianceGateResult &&
        !r.complianceGateResult.skipped &&
        r.complianceGateResult.score !== null) {
        const cgScore = r.complianceGateResult.score;
        if (cgScore >= 90) {
            lines.push(`\n🔒 Compliance: ${String(cgScore)}/100`);
        }
        else {
            const issueText = r.complianceGateResult.issues.length > 0
                ? ` — ${r.complianceGateResult.issues.join(', ')}`
                : '';
            lines.push(`\n⚠️ Compliance: ${String(cgScore)}/100${issueText}`);
        }
    }
    // SPEC-448: Version snapshot tag
    if (r.versionSnapshotTag) {
        lines.push(`\n📌 Snapshot: ${r.versionSnapshotTag}`);
    }
    // SPEC-694: Orchestration plan for cross-module/architectural specs on approved
    if (r.orchestrationPlan) {
        const v = r.orchestrationPlan.parallelSafetyVerdict ? 'parallel-safe' : 'sequential-required';
        lines.push(`\n🤖 Orchestration: ${String(r.orchestrationPlan.executionOrder.length)} waves | ${v}`);
    }
    // SPEC-494: Claude Code mode hint
    if (r.suggestedClaudeMode) {
        lines.push(`\n💡 **Suggested Claude mode:** \`${r.suggestedClaudeMode}\` — ${r.modeHint ?? ''}`);
    }
    if (recordActualHint) {
        lines.push(`\n💡 ${recordActualHint}`);
    }
    // SPEC-754: Shell hygiene reminder for claude-code host on done transition
    if (shellHygieneHint) {
        lines.push(`\n🐚 **Shell hygiene:** ${shellHygieneHint}`);
    }
    // SPEC-340: nextAction and lifecycleMap
    const nextAction = buildNextAction(newStatus);
    const lifecycleMap = buildLifecycleMap(newStatus);
    lines.push(buildLifecycleMapLine(lifecycleMap));
    lines.push(`\n**Next step:** ${nextAction.step}\n> ${nextAction.prompt}\n> \`${nextAction.suggestedCommand}\` — ${nextAction.whenToDoIt}`);
    const allNextSteps = [...(r.implementingSuggestions ?? [])];
    const baseText = formatSuccess(t('tools.response.statusTitle'), lines.join(''));
    const withNextSteps = allNextSteps.length > 0 ? addNextSteps(baseText, allNextSteps) : baseText;
    const markdownText = reconciliationMarkdown
        ? `${withNextSteps}\n\n${reconciliationMarkdown}`
        : withNextSteps;
    const displayTitle = specTitle ?? `SPEC-${specId}`;
    const humanSummary = buildUpdateStatusSummary(displayTitle, newStatus);
    return {
        content: [
            { type: 'text', text: markdownText },
            { type: 'text', text: humanSummary },
        ],
        structuredContent: { ...result, nextAction, lifecycleMap, humanSummary },
    };
}
/** Render a compact lifecycle map line showing current, next, and remaining steps */
function buildLifecycleMapLine(map) {
    const parts = map.stages.map((stage) => {
        if (stage === map.current) {
            return `**[${stage}]**`;
        }
        if (map.remaining.includes(stage) || stage === map.next) {
            return stage;
        }
        return `~~${stage}~~`;
    });
    return `\n📍 ${parts.join(' → ')}`;
}
//# sourceMappingURL=response-builder.js.map