/**
 * commands/host-detect.mjs — host-detect + reconcile commands (C29).
 *
 * Layer 1 (post-CLI-layering refactor, subtask 6 pilot). Both functions
 * return { envelope, exitCode } — they MUST NOT call process.exit, output(),
 * or fail() directly. The Layer 2 wrapper (dispatch.mjs `wrap()`) writes
 * stdout and exits.
 */

import { existsSync, readFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { detectHost } from '../host/detect.mjs'
import { resolveMode } from '../host/resolve.mjs'
import { err, ok } from '../util/result.mjs'

export function cmdHostDetect() {
	const host = detectHost()
	return ok({
		status: 'ok',
		command: 'host-detect',
		host,
	})
}

/**
 * Parse `--track <quick|standard|deep>` from positional args. Returns the
 * lowercased track or null when the flag is absent. Unknown values are
 * silently ignored to preserve backward-compat — the caller falls back to
 * global phase_delegation in that case.
 */
function parseTrackFlag(args) {
	if (!Array.isArray(args)) return null
	const idx = args.indexOf('--track')
	if (idx === -1 || idx === args.length - 1) return null
	const val = String(args[idx + 1]).toLowerCase()
	return val === 'quick' || val === 'standard' || val === 'deep' ? val : null
}

export function cmdReconcile(projectDir, extraArgs = []) {
	if (!projectDir)
		return err('Usage: apt-tools reconcile <project-dir> [--track quick|standard|deep]')
	const targetDir = resolve(projectDir)

	if (!existsSync(targetDir)) return err(`Directory does not exist: ${targetDir}`)

	const host = detectHost()
	const { capabilities } = host
	const track = parseTrackFlag(extraArgs)

	// Read orchestration config — default all fields to 'auto' if missing
	let orchestrationConfig = {
		phase_delegation: 'auto',
		review_mode: 'auto',
		debate_mode: 'auto',
	}
	let perTrack = null

	const configPath = join(targetDir, '.aperant', 'config.json')
	if (existsSync(configPath)) {
		try {
			const cfg = JSON.parse(readFileSync(configPath, 'utf-8'))
			if (cfg.orchestration) {
				orchestrationConfig = {
					phase_delegation: cfg.orchestration.phase_delegation ?? 'auto',
					review_mode: cfg.orchestration.review_mode ?? 'auto',
					debate_mode: cfg.orchestration.debate_mode ?? 'auto',
				}
				perTrack = cfg.orchestration.per_track ?? null
			}
		} catch {
			// Malformed config — use defaults
		}
	}

	// Per-track phase_delegation override (roundtable 2026-05-14 R7):
	// when --track is passed AND per_track[track] is set, use that as
	// the requested mode for phase_delegation. Otherwise fall back to
	// the global value. review_mode and debate_mode are not track-scoped.
	const requestedPhaseDelegation =
		track && perTrack?.[track] ? perTrack[track] : orchestrationConfig.phase_delegation

	// Resolve each dimension
	const pdResult = resolveMode(requestedPhaseDelegation, capabilities, 'phase_delegation')
	const rmResult = resolveMode(orchestrationConfig.review_mode, capabilities, 'review_mode')
	const dmResult = resolveMode(orchestrationConfig.debate_mode, capabilities, 'debate_mode')

	const resolved = {
		phase_delegation: pdResult.resolved,
		review_mode: rmResult.resolved,
		debate_mode: dmResult.resolved,
	}

	const downgrades = [pdResult.downgrade, rmResult.downgrade, dmResult.downgrade].filter(Boolean)

	const result = {
		status: 'ok',
		command: 'reconcile',
		host: { cli: host.cli, version: host.version, capabilities },
		config: orchestrationConfig,
		resolved,
	}

	if (track) {
		result.track = track
		result.track_source = perTrack && perTrack[track] ? 'per_track' : 'fallback'
	}

	if (downgrades.length > 0) {
		result.downgrades = downgrades
	}

	return ok(result)
}
