import { hashProjectPath } from '../storage/base-store.js';
import { previewDeleteSpec, executeDeleteSpec } from '../engine/deleter/core.js';
import { ti } from '../i18n/index.js';
import { regenerateSpecSummaryHtml } from '../engine/spec-summary-html.js';
import { specStore } from '../storage/index.js';
import { elicitOrFallback, buildConfirmSchema } from '../engine/elicitation/elicit-helper.js';
import { acquireLock, releaseLock, LockBusyError } from '../engine/safety/cross-process-lock.js';
/** Build the fallback interactiveQuestion for delete confirmation. */
function buildDeleteFallback(specIds) {
    const label = specIds.length === 1 ? (specIds[0] ?? 'spec') : `${specIds.length} specs`;
    return {
        header: 'Delete',
        question: `Are you sure you want to delete ${label}? This cannot be undone.`,
        multiSelect: false,
        options: [
            { label: 'cancel', description: 'Cancel — keep the spec(s) (Recommended)' },
            { label: 'confirm', description: 'Delete permanently' },
        ],
    };
}
/**
 * Handle delete_spec tool invocation.
 * Supports single or bulk spec deletion with soft/hard delete.
 * SPEC-595: When confirm is omitted and server supports elicitation, fires a
 * destructive-confirm elicit (default = cancel). Falls back to interactiveQuestions[].
 */
export async function handleDeleteSpec(params, server) {
    try {
        const projectId = hashProjectPath(params.projectRoot);
        const specIds = Array.isArray(params.specId) ? params.specId : [params.specId];
        const confirm = params.confirm ?? false;
        const force = params.force ?? false;
        if (!confirm) {
            const preview = await previewDeleteSpec(projectId, specIds);
            // SPEC-595: Elicit confirmation instead of returning a plain preview
            if (server !== undefined) {
                const label = specIds.length === 1 ? (specIds[0] ?? 'spec') : `${specIds.length} spec(s)`;
                const { field, property } = buildConfirmSchema('action', `Delete ${label}`, 'Cancel — keep spec(s)');
                const schema = { type: 'object', properties: { [field]: property } };
                const fallback = buildDeleteFallback(specIds);
                const outcome = await elicitOrFallback(server, `Confirm deletion of ${label}. This is a destructive operation.`, schema, [fallback]);
                if (outcome.mode === 'native') {
                    // cancel or decline — no-op, return preview without executing
                    if (outcome.action !== 'accept' || outcome.content?.action !== 'confirm') {
                        return {
                            content: [{ type: 'text', text: 'Deletion cancelled.' }],
                            structuredContent: preview,
                        };
                    }
                    // user confirmed via elicitation — fall through to execute below
                }
                else {
                    // fallback path — return interactiveQuestions so LLM can relay via AskUserQuestion
                    return {
                        content: [
                            {
                                type: 'text',
                                text: '⚡ INTERACTIVE — call AskUserQuestion now with the interactiveQuestions from structuredContent',
                            },
                        ],
                        structuredContent: {
                            ...preview,
                            interactiveQuestions: outcome.interactiveQuestions,
                        },
                    };
                }
            }
            else {
                // Programmatic path with no server — return preview only (automation-safe)
                return {
                    content: [
                        {
                            type: 'text',
                            text: ti('tools.delete_spec.preview', { count: String(preview.itemsAffected) }),
                        },
                    ],
                    structuredContent: preview,
                };
            }
        }
        // SPEC-719: Acquire cross-process lock for each spec before deletion.
        // For bulk deletes, we acquire locks sequentially and release all in finally.
        const lockHandles = [];
        const busySpecs = [];
        for (const sid of specIds) {
            const handle = await acquireLock(params.projectRoot, sid, { reason: 'delete_spec' });
            if (handle === null) {
                busySpecs.push(sid);
            }
            else {
                lockHandles.push(handle);
            }
        }
        if (busySpecs.length > 0) {
            // Release already-acquired handles before returning error
            await Promise.all(lockHandles.map((h) => (h !== null ? releaseLock(h) : Promise.resolve())));
            return {
                content: [
                    {
                        type: 'text',
                        text: `Cannot delete: spec(s) ${busySpecs.join(', ')} are locked by another process (LOCK_BUSY).`,
                    },
                ],
                isError: true,
            };
        }
        try {
            const result = await executeDeleteSpec(projectId, specIds, force);
            if (!result.success) {
                return {
                    content: [
                        {
                            type: 'text',
                            text: result.warnings.length > 0 ? result.warnings.join('\n') : 'Delete failed.',
                        },
                    ],
                    isError: true,
                    structuredContent: result,
                };
            }
            // Regenerate dashboard after successful deletion (best-effort, non-blocking)
            void specStore
                .listSpecs(projectId)
                .then((specs) => regenerateSpecSummaryHtml(params.projectRoot, specs, []));
            return {
                content: [
                    {
                        type: 'text',
                        text: ti('tools.delete_spec.success', { count: String(result.itemsAffected) }),
                    },
                ],
                structuredContent: result,
            };
        }
        finally {
            // SPEC-719: Release all acquired locks
            await Promise.all(lockHandles.map((h) => h !== null
                ? releaseLock(h).catch((err) => {
                    console.warn('[planu:lock] delete_spec release error', {
                        error: err instanceof Error ? err.message : String(err),
                    });
                })
                : Promise.resolve()));
        }
    }
    catch (error) {
        if (error instanceof LockBusyError) {
            return {
                content: [
                    { type: 'text', text: `Spec is locked by another process (LOCK_BUSY). Retry later.` },
                ],
                isError: true,
            };
        }
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [{ type: 'text', text: ti('tools.delete_spec.error', { message }) }],
            isError: true,
        };
    }
}
//# sourceMappingURL=delete-spec.js.map