/**
 * headless-status.ts — direct `sf headless status` implementation.
 *
 * Purpose: keep the headless status machine surface read-only and
 * TTY-independent instead of routing through the interactive `/status` overlay
 * command or the long-lived RPC/v2 session handshake.
 */
import { buildQuerySnapshot, type QuerySnapshot } from "./headless-query.js";

export interface HeadlessStatusResult {
	exitCode: number;
	data?: QuerySnapshot;
}

/**
 * Render a compact text status from the query snapshot.
 *
 * Purpose: provide the same operator value as `/status` in terminals where no
 * interactive overlay can be displayed.
 *
 * Consumer: handleHeadlessStatus for text-mode `sf headless status`.
 */
export function formatHeadlessStatus(snapshot: QuerySnapshot): string {
	const { next, runtime, uokDiagnostics, schedule } = snapshot;
	const state = snapshot.state as any;
	const lines = ["SF Status", ""];
	lines.push(`Phase: ${state.phase}`);
	if (state.activeMilestone) {
		lines.push(
			`Active milestone: ${state.activeMilestone.id} - ${state.activeMilestone.title}`,
		);
	}
	if (state.activeSlice) {
		lines.push(
			`Active slice: ${state.activeSlice.id} - ${state.activeSlice.title}`,
		);
	}
	if (state.activeTask) {
		lines.push(
			`Active task: ${state.activeTask.id} - ${state.activeTask.title}`,
		);
	}
	const progress = state.progress;
	if (progress) {
		const parts = [
			`milestones ${progress.milestones.done}/${progress.milestones.total}`,
		];
		if (progress.slices)
			parts.push(`slices ${progress.slices.done}/${progress.slices.total}`);
		if (progress.tasks)
			parts.push(`tasks ${progress.tasks.done}/${progress.tasks.total}`);
		lines.push(`Progress: ${parts.join(", ")}`);
	}
	if (state.nextAction) lines.push(`Next: ${state.nextAction}`);
	if (state.blockers.length > 0)
		lines.push(`Blockers: ${state.blockers.join("; ")}`);
	lines.push("");
	lines.push(
		`Dispatch: ${next.action}${next.unitType ? ` ${next.unitType}` : ""}${next.unitId ? ` ${next.unitId}` : ""}${next.reason ? ` - ${next.reason}` : ""}`,
	);
	if (uokDiagnostics) {
		lines.push(
			`UOK: ${uokDiagnostics.verdict ?? "unknown"} (${uokDiagnostics.classification ?? "unknown"})`,
		);
	}
	if (runtime.units.length > 0) {
		lines.push("");
		lines.push("Runtime units:");
		for (const unit of runtime.units.slice(0, 8)) {
			lines.push(`  ${unit.unitType} ${unit.unitId}: ${unit.status}`);
		}
	}
	if (schedule) {
		lines.push("");
		lines.push(
			`Schedule: ${schedule.pending_count} pending, ${schedule.overdue_count} overdue`,
		);
	}
	if (state.registry.length > 0) {
		lines.push("");
		lines.push("Milestones:");
		for (const milestone of state.registry) {
			lines.push(`  ${milestone.id}: ${milestone.title} (${milestone.status})`);
		}
	}
	return lines.join("\n");
}

/**
 * Handle `sf headless status` without spawning the interactive RPC child.
 *
 * Purpose: avoid the long-standing v2 init timeout for a command whose answer
 * is fully available from DB-backed project state.
 *
 * Consumer: runHeadlessOnce direct-command bypass.
 */
export async function handleHeadlessStatus(
	basePath: string,
	options: { json?: boolean } = {},
): Promise<HeadlessStatusResult> {
	const snapshot = await buildQuerySnapshot(basePath);
	if (options.json) {
		process.stdout.write(JSON.stringify(snapshot) + "\n");
	} else {
		process.stdout.write(formatHeadlessStatus(snapshot) + "\n");
	}
	return { exitCode: 0, data: snapshot };
}
