// SF — reopen-milestone tool handler
/**
 * reopen-milestone handler — the core operation behind sf_milestone_reopen.
 *
 * Resets a closed milestone back to "active", all of its slices to
 * "in_progress", and all tasks to "pending". Cleans up stale filesystem
 * artifacts so the DB-filesystem reconciler does not auto-correct
 * entities back to "complete".
 */
import { existsSync, unlinkSync } from "node:fs";
import { join } from "node:path";
import { debugLog } from "../debug-logger.js";
import {
	clearPathCache,
	resolveMilestonePath,
	resolveSlicePath,
	resolveTasksDir,
} from "../paths.js";
import {
	getMilestone,
	getMilestoneSlices,
	getSliceTasks,
	transaction,
	updateMilestoneStatus,
	updateSliceStatus,
	updateTaskStatus,
} from "../sf-db.js";
import { invalidateStateCache } from "../state.js";
import { isClosedStatus } from "../status-guards.js";
import { isNonEmptyString } from "../validation.js";
import { logWarning } from "../workflow-logger.js";
import { runPostMutationHook } from "./tool-helpers.js";
export async function handleReopenMilestone(params, basePath) {
	// ── Validate required fields ────────────────────────────────────────────
	if (!isNonEmptyString(params.milestoneId)) {
		return { error: "milestoneId is required and must be a non-empty string" };
	}
	// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
	let guardError = null;
	let slicesResetCount = 0;
	let tasksResetCount = 0;
	transaction(() => {
		const milestone = getMilestone(params.milestoneId);
		if (!milestone) {
			guardError = `milestone not found: ${params.milestoneId}`;
			return;
		}
		if (!isClosedStatus(milestone.status)) {
			guardError = `milestone ${params.milestoneId} is not closed (status: ${milestone.status}) — nothing to reopen`;
			return;
		}
		updateMilestoneStatus(params.milestoneId, "active", null);
		const slices = getMilestoneSlices(params.milestoneId);
		slicesResetCount = slices.length;
		for (const slice of slices) {
			updateSliceStatus(params.milestoneId, slice.id, "in_progress");
			const tasks = getSliceTasks(params.milestoneId, slice.id);
			tasksResetCount += tasks.length;
			for (const task of tasks) {
				updateTaskStatus(params.milestoneId, slice.id, task.id, "pending");
			}
		}
	});
	if (guardError) {
		return { error: guardError };
	}
	// ── Invalidate caches ────────────────────────────────────────────────────
	invalidateStateCache();
	// ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
	// Without this, the DB-filesystem reconciler sees SUMMARY.md files and
	// auto-corrects entities back to "complete", making reopen a no-op (#3161).
	try {
		const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
		if (milestoneDir) {
			const milestoneSummary = join(
				milestoneDir,
				`${params.milestoneId}-SUMMARY.md`,
			);
			if (existsSync(milestoneSummary)) unlinkSync(milestoneSummary);
		}
		const slices = getMilestoneSlices(params.milestoneId);
		for (const slice of slices) {
			const sliceDir = resolveSlicePath(basePath, params.milestoneId, slice.id);
			if (sliceDir) {
				const sliceSummary = join(sliceDir, `${slice.id}-SUMMARY.md`);
				if (existsSync(sliceSummary)) unlinkSync(sliceSummary);
				const sliceUat = join(sliceDir, `${slice.id}-UAT.md`);
				if (existsSync(sliceUat)) unlinkSync(sliceUat);
			}
			const tasksDir = resolveTasksDir(basePath, params.milestoneId, slice.id);
			if (tasksDir) {
				const tasks = getSliceTasks(params.milestoneId, slice.id);
				for (const task of tasks) {
					const taskSummary = join(tasksDir, `${task.id}-SUMMARY.md`);
					if (existsSync(taskSummary)) unlinkSync(taskSummary);
				}
			}
		}
	} catch (err) {
		debugLog("reopen-milestone-cleanup-failed", {
			milestoneId: params.milestoneId,
			error: String(err),
		});
	}
	clearPathCache();
	// ── Post-mutation hook ───────────────────────────────────────────────────
	await runPostMutationHook(
		basePath,
		params.milestoneId,
		{
			cmd: "reopen-milestone",
			params: {
				milestoneId: params.milestoneId,
				reason: params.reason ?? null,
				slicesReset: slicesResetCount,
				tasksReset: tasksResetCount,
			},
			ts: new Date().toISOString(),
			actor: "agent",
			actor_name: params.actorName,
			trigger_reason: params.triggerReason,
		},
		{ caller: "reopen-milestone" },
	);
	return {
		milestoneId: params.milestoneId,
		slicesReset: slicesResetCount,
		tasksReset: tasksResetCount,
	};
}
