package infra

// Termination labels returned by ClassifyFleetTermination. They describe the
// mechanical termination state of a Claude fleet agent so a cheap (LLM-free)
// watcher can decide what to do with it.
const (
	// TerminationReclama means the agent is asking for human input and must be
	// attended first, above any other consideration.
	TerminationReclama = "RECLAMA"
	// TerminationMalLanzado means the agent was launched without a DoD contract
	// — no agent should run without an acceptance criterion.
	TerminationMalLanzado = "MAL_LANZADO"
	// TerminationDiceTerminado means the agent claims it is finished (idle and
	// either phase "hecho" or its DoD status is "met").
	TerminationDiceTerminado = "DICE_TERMINADO"
	// TerminationEstancado means the agent is idle, not finished, and has been
	// inactive at or beyond the stall threshold.
	TerminationEstancado = "ESTANCADO"
	// TerminationTrabajando means the agent is still working (busy, or idle
	// recently below the stall threshold).
	TerminationTrabajando = "TRABAJANDO"
)

// ClassifyFleetTermination mechanically classifies the termination state of a
// fleet agent. It is pure and deterministic: no I/O, no clock, no global state.
//
// Inputs:
//   - status: process state from sessions.json — "idle" | "busy" | "waiting".
//   - phase: work phase from goal.json — "investigando", "planificando",
//     "haciendo", "testeando", "puliendo", "pendiente_revision", "preguntando",
//     "bloqueado", "en_pausa", "hecho", "iterando" or "".
//   - dodContract: fixed acceptance criterion ("" means none was defined).
//   - dodStatus: "pending" | "met" | "failed" | "".
//   - idleSeconds: seconds since the session's last activity.
//   - stallThresholdSeconds: threshold to consider the agent stalled.
//
// Precedence (evaluated top to bottom; the first match wins):
//  1. RECLAMA — the agent is asking for human input (status "waiting" OR phase
//     "preguntando"/"bloqueado"). This dominates everything, even a missing DoD
//     contract: if it asks for input, that is the first thing to handle.
//  2. MAL_LANZADO — it does not reclaim input but has no DoD contract; no agent
//     should run without one.
//  3. DICE_TERMINADO — idle AND (phase "hecho" OR dodStatus "met").
//  4. ESTANCADO — idle AND phase not "hecho" AND idleSeconds >= stall threshold.
//  5. TRABAJANDO — everything else (busy, or idle recently below the threshold).
func ClassifyFleetTermination(status, phase, dodContract, dodStatus string, idleSeconds, stallThresholdSeconds int) string {
	// 1. RECLAMA dominates: a request for human input is handled first.
	if status == "waiting" || phase == "preguntando" || phase == "bloqueado" {
		return TerminationReclama
	}

	// 2. MAL_LANZADO: running without a DoD contract is invalid.
	if dodContract == "" {
		return TerminationMalLanzado
	}

	// 3. DICE_TERMINADO: idle and self-reporting completion.
	if status == "idle" && (phase == "hecho" || dodStatus == "met") {
		return TerminationDiceTerminado
	}

	// 4. ESTANCADO: idle, not finished, inactive at/beyond the stall threshold.
	if status == "idle" && phase != "hecho" && idleSeconds >= stallThresholdSeconds {
		return TerminationEstancado
	}

	// 5. TRABAJANDO: busy, or idle recently below the threshold.
	return TerminationTrabajando
}
