/**
 * commands/active.mjs — active-board list/show command (C29).
 *
 * C34: reads exclusively from the per-agent `team-status/` directory. The
 * legacy `active.json` fallback has been removed — if no live entries exist,
 * we return an empty board.
 *
 * C22: stdout JSON envelope is unchanged. When stdout is a TTY, a
 * human-readable bullet list is written to stderr as a sidecar preview.
 */

import { resolve } from 'node:path'
import { createCoordinationStore } from '../coordination/store.mjs'
import { toActiveBoardShape } from '../coordination/team-status.mjs'
import { bullet, section, supportsColor } from '../output-style/index.mjs'
import { updateTeamMember } from '../team/team.mjs'
import { parseFlags } from '../util/args.mjs'
import { err, ok } from '../util/result.mjs'

/**
 * Emit a human-readable preview to stderr when stdout is a TTY. Never throws.
 * See commands/state.mjs for the shared rationale (C22).
 */
function emitTtyPreview(buildLines) {
	try {
		if (!process.stdout.isTTY) return
		const color = supportsColor({ stream: process.stdout, env: process.env })
		const lines = buildLines(color)
		if (!lines || lines.length === 0) return
		process.stderr.write(lines.join('\n') + '\n')
	} catch {
		/* stderr sidecar must never crash the main command */
	}
}

export function cmdActive(subcommand, projectDir, extraArgs = []) {
	if (!subcommand) return err('Usage: apt-tools active <list|show> <project-dir> [--scope <s>]')
	if (!projectDir)
		return err('Usage: apt-tools active ' + subcommand + ' <project-dir> [--scope <s>]')

	const targetDir = resolve(projectDir)
	updateTeamMember(targetDir)
	const store = createCoordinationStore(targetDir)
	const flags = parseFlags(extraArgs)
	const scopeFilter = flags.get('scope') || null
	const includeStale = flags.has('include-stale')

	// Read exclusively from the per-agent team-status/ directory (C34).
	// R4 liveness filtering hides dead entries unless --include-stale is passed.
	const records = store.listTeamStatus({ includeStale })
	const board = toActiveBoardShape(records)

	let entries = Object.values(board.active || {})
	if (scopeFilter) {
		entries = entries.filter((e) => (e?.scope || 'project') === scopeFilter)
	}

	switch (subcommand) {
		case 'list':
		case 'show': {
			// C22 — TTY-only sidecar preview (written before return so the
			// stderr message lands first; stdout is written by wrap()).
			emitTtyPreview((color) => {
				const header = section(`Active Agents (${entries.length})`, { color })
				if (entries.length === 0) {
					return [header, bullet('no live agents', undefined, { color })]
				}
				const rows = entries.map((e) => {
					const label = `${e?.owner || e?.agentId || 'unknown'} — ${e?.description || e?.taskId || '—'}`
					const status = e?.lifecycle_phase === 'completed' ? 'ok' : 'pending'
					return bullet(label, status, { color })
				})
				return [header, ...rows]
			})
			return ok({
				status: 'ok',
				command: 'active-' + subcommand,
				active: entries,
				count: entries.length,
				updated_at: board.updated_at,
			})
		}
		default:
			return err(`Unknown active subcommand: ${subcommand}. Expected: list, show`)
	}
}
