function matchesScope(unitId, scope) {
	if (!scope) return true;
	if (unitId === "project" || unitId === "environment") return true;
	return (
		unitId === scope ||
		unitId.startsWith(`${scope}/`) ||
		unitId.startsWith(`${scope}`)
	);
}
export function summarizeDoctorIssues(issues) {
	const errors = issues.filter((issue) => issue.severity === "error").length;
	const warnings = issues.filter(
		(issue) => issue.severity === "warning",
	).length;
	const infos = issues.filter((issue) => issue.severity === "info").length;
	const fixable = issues.filter((issue) => issue.fixable).length;
	const byCodeMap = new Map();
	for (const issue of issues) {
		byCodeMap.set(issue.code, (byCodeMap.get(issue.code) ?? 0) + 1);
	}
	const byCode = [...byCodeMap.entries()]
		.map(([code, count]) => ({ code, count }))
		.sort((a, b) => b.count - a.count || a.code.localeCompare(b.code));
	return { total: issues.length, errors, warnings, infos, fixable, byCode };
}
export function filterDoctorIssues(issues, options) {
	let filtered = issues;
	if (options?.scope)
		filtered = filtered.filter((issue) =>
			matchesScope(issue.unitId, options.scope),
		);
	if (!options?.includeWarnings)
		filtered = filtered.filter((issue) => issue.severity === "error");
	return filtered;
}
export function formatDoctorReport(report, options) {
	const scopedIssues = filterDoctorIssues(report.issues, {
		scope: options?.scope,
		includeWarnings: options?.includeWarnings ?? true,
	});
	const summary = summarizeDoctorIssues(scopedIssues);
	const maxIssues = options?.maxIssues ?? 12;
	const lines = [];
	lines.push(
		options?.title ??
			(summary.errors > 0
				? "SF doctor found blocking issues."
				: "SF doctor report."),
	);
	lines.push(`Scope: ${options?.scope ?? "all milestones"}`);
	lines.push(
		`Issues: ${summary.total} total · ${summary.errors} error(s) · ${summary.warnings} warning(s) · ${summary.fixable} fixable`,
	);
	if (summary.byCode.length > 0) {
		lines.push("Top issue types:");
		for (const item of summary.byCode.slice(0, 5)) {
			lines.push(`- ${item.code}: ${item.count}`);
		}
	}
	if (scopedIssues.length > 0) {
		lines.push("Priority issues:");
		for (const issue of scopedIssues.slice(0, maxIssues)) {
			const prefix =
				issue.severity === "error"
					? "ERROR"
					: issue.severity === "warning"
						? "WARN"
						: "INFO";
			lines.push(
				`- [${prefix}] ${issue.unitId}: ${issue.message}${issue.file ? ` (${issue.file})` : ""}`,
			);
		}
		if (scopedIssues.length > maxIssues) {
			lines.push(`- ...and ${scopedIssues.length - maxIssues} more in scope`);
		}
	}
	if (report.fixesApplied.length > 0) {
		lines.push("Fixes applied:");
		for (const fix of report.fixesApplied.slice(0, maxIssues))
			lines.push(`- ${fix}`);
		if (report.fixesApplied.length > maxIssues)
			lines.push(`- ...and ${report.fixesApplied.length - maxIssues} more`);
	}
	return lines.join("\n");
}
export function formatDoctorIssuesForPrompt(issues) {
	if (issues.length === 0) return "- No remaining issues in scope.";
	return issues
		.map((issue) => {
			const prefix =
				issue.severity === "error"
					? "ERROR"
					: issue.severity === "warning"
						? "WARN"
						: "INFO";
			return `- [${prefix}] ${issue.unitId} | ${issue.code} | ${issue.message}${issue.file ? ` | file: ${issue.file}` : ""} | fixable: ${issue.fixable ? "yes" : "no"}`;
		})
		.join("\n");
}
/**
 * Serialize a doctor report to JSON — suitable for CI/tooling integration.
 * Usage: /doctor --json
 */
export function formatDoctorReportJson(report) {
	return JSON.stringify(
		{
			ok: report.ok,
			basePath: report.basePath,
			generatedAt: new Date().toISOString(),
			summary: summarizeDoctorIssues(report.issues),
			issues: report.issues,
			fixesApplied: report.fixesApplied,
			...(report.timing ? { timing: report.timing } : {}),
		},
		null,
		2,
	);
}
