import { PERSISTENT_GOAL_CUSTOM_KEY, defaultMaxTurns, mergeCustomDataPatch, readPersistentGoal, serializePersistentGoal } from "../../../agent/goals/state.js";
import { applyPersistentGoalUserAction } from "../../../agent/goals/patch-from-user-action.js";
import { applyChecklistUserMutation } from "../../../agent/goals/checklist-user.js";
import { mergePersistentGoalUiLocale, normalizeGoalUiLocale } from "../../../agent/goals/goal-locale.js";
import { listGoalRuns } from "../../../agent/goals/goal-run-store.js";
//#region src/gateway/hono/routes/goals.ts
function isGoalAction(x) {
	return x === "pause" || x === "resume" || x === "clear" || x === "restart";
}
/** Webchat persistent `/goal` REST API. */
function registerGoalsRoutes(authenticated, deps) {
	const sm = deps.service.sessionIndexInstance;
	const cfg = () => deps.service.currentConfig;
	authenticated.get("/api/goals/webchat", async (c) => {
		const sessionKey = c.req.query("sessionKey")?.trim();
		if (!sessionKey) return c.json({
			ok: false,
			error: "Missing sessionKey"
		}, 400);
		const uiLocale = normalizeGoalUiLocale(c.req.query("uiLocale"));
		let m = await sm.getSessionMetadata(sessionKey);
		if (uiLocale && m) {
			const merged = mergePersistentGoalUiLocale(m.customData, uiLocale);
			if (merged !== m.customData) {
				await sm.updateSessionMetadata(sessionKey, { customData: merged });
				m = await sm.getSessionMetadata(sessionKey);
			}
		}
		const goal = readPersistentGoal(m?.customData);
		return c.json({
			ok: true,
			sessionKey,
			persistentGoal: goal
		});
	});
	authenticated.get("/api/goals/webchat/runs", async (c) => {
		const sessionKey = c.req.query("sessionKey")?.trim();
		if (!sessionKey) return c.json({
			ok: false,
			error: "Missing sessionKey"
		}, 400);
		const limitRaw = c.req.query("limit")?.trim();
		let limit = 50;
		if (limitRaw) {
			const n = Number.parseInt(limitRaw, 10);
			if (Number.isFinite(n)) limit = Math.min(500, Math.max(1, n));
		}
		const runs = await listGoalRuns(cfg(), sessionKey, { limit });
		return c.json({
			ok: true,
			sessionKey,
			runs
		});
	});
	authenticated.post("/api/goals/webchat", async (c) => {
		const body = await c.req.json().catch(() => ({}));
		const sessionKey = typeof body.sessionKey === "string" ? body.sessionKey.trim() : "";
		if (!sessionKey) return c.json({
			ok: false,
			error: "Missing sessionKey"
		}, 400);
		const goalsSlice = cfg().goals;
		const actionRaw = body.action ?? (body.clear === true ? "clear" : void 0);
		if (isGoalAction(actionRaw)) {
			const meta = await sm.getSessionMetadata(sessionKey);
			if (!meta) return c.json({
				ok: false,
				error: "Session not found"
			}, 404);
			const applied = applyPersistentGoalUserAction(meta.customData, actionRaw, goalsSlice);
			if (applied.kind === "error") return c.json({
				ok: false,
				error: applied.error
			}, 400);
			if (applied.kind === "noop") {
				const persistentGoal = readPersistentGoal(meta.customData);
				return c.json({
					ok: true,
					sessionKey,
					noop: true,
					message: applied.message,
					persistentGoal
				});
			}
			const uiLocale = normalizeGoalUiLocale(body.uiLocale);
			const customData = uiLocale != null ? mergePersistentGoalUiLocale(applied.customData, uiLocale) ?? applied.customData : applied.customData;
			await sm.updateSessionMetadata(sessionKey, { customData });
			const persistentGoal = readPersistentGoal((await sm.getSessionMetadata(sessionKey))?.customData);
			if (applied.kickoff) deps.service.enqueueWebchatPersistentGoalKickoff(sessionKey, applied.kickoff);
			return c.json({
				ok: true,
				sessionKey,
				action: actionRaw,
				persistentGoal
			});
		}
		if (body.clear === true) {
			const meta = await sm.getSessionMetadata(sessionKey);
			if (!meta) return c.json({
				ok: false,
				error: "Session not found"
			}, 404);
			const base = { ...meta.customData };
			delete base[PERSISTENT_GOAL_CUSTOM_KEY];
			await sm.updateSessionMetadata(sessionKey, { customData: base });
			return c.json({
				ok: true,
				sessionKey,
				cleared: true
			});
		}
		const goalText = typeof body.goalText === "string" ? body.goalText.trim() : "";
		if (!goalText) return c.json({
			ok: false,
			error: "Missing goalText (or set clear:true)"
		}, 400);
		const meta = await sm.getSessionMetadata(sessionKey);
		if (!meta) return c.json({
			ok: false,
			error: "Session not found"
		}, 404);
		const maxTurns = typeof body.maxTurns === "number" && Number.isFinite(body.maxTurns) ? Math.max(1, Math.min(500, Math.floor(body.maxTurns))) : defaultMaxTurns(cfg().goals);
		const judgeModelRef = typeof body.judgeModelRef === "string" && body.judgeModelRef.trim() ? body.judgeModelRef.trim() : typeof cfg().goals?.judgeModelRef === "string" ? cfg().goals.judgeModelRef.trim() : void 0;
		const uiLocale = normalizeGoalUiLocale(body.uiLocale);
		const next = {
			goal: goalText,
			status: "active",
			turnsUsed: 0,
			maxTurns,
			createdAt: Date.now(),
			lastTurnAt: 0,
			decomposed: false,
			consecutiveParseFailures: 0,
			...judgeModelRef ? { judgeModelRef } : {},
			...uiLocale ? { uiLocale } : {}
		};
		const customData = mergeCustomDataPatch({ ...meta.customData }, { [PERSISTENT_GOAL_CUSTOM_KEY]: serializePersistentGoal(next) });
		await sm.updateSessionMetadata(sessionKey, { customData });
		const persistentGoal = readPersistentGoal((await sm.getSessionMetadata(sessionKey))?.customData);
		deps.service.enqueueWebchatPersistentGoalKickoff(sessionKey, goalText);
		return c.json({
			ok: true,
			sessionKey,
			persistentGoal
		});
	});
	/** Checklist CRUD for standing goals (`/subgoal` parity for webchat). */
	authenticated.post("/api/goals/webchat/checklist", async (c) => {
		const body = await c.req.json().catch(() => ({}));
		const sessionKey = typeof body.sessionKey === "string" ? body.sessionKey.trim() : "";
		if (!sessionKey) return c.json({
			ok: false,
			error: "Missing sessionKey"
		}, 400);
		const op = typeof body.op === "string" ? body.op.trim().toLowerCase() : "";
		const meta = await sm.getSessionMetadata(sessionKey);
		if (!meta) return c.json({
			ok: false,
			error: "Session not found"
		}, 404);
		let mutation = null;
		if (op === "reset") mutation = applyChecklistUserMutation(meta.customData, { type: "reset" });
		else if (op === "add") {
			const text = typeof body.text === "string" ? body.text : "";
			mutation = applyChecklistUserMutation(meta.customData, {
				type: "add",
				text
			});
		} else if (op === "remove") {
			const index = typeof body.index === "number" && Number.isFinite(body.index) ? Math.floor(body.index) : void 0;
			if (index === void 0 || index < 1) return c.json({
				ok: false,
				error: "Missing or invalid index (1-based)"
			}, 400);
			mutation = applyChecklistUserMutation(meta.customData, {
				type: "remove",
				index1Based: index
			});
		} else if (op === "mark") {
			const index = typeof body.index === "number" && Number.isFinite(body.index) ? Math.floor(body.index) : void 0;
			const status = typeof body.status === "string" ? body.status.trim().toLowerCase() : "";
			if (index === void 0 || index < 1) return c.json({
				ok: false,
				error: "Missing or invalid index (1-based)"
			}, 400);
			if (status !== "pending" && status !== "completed" && status !== "impossible") return c.json({
				ok: false,
				error: "status must be pending, completed, or impossible"
			}, 400);
			mutation = applyChecklistUserMutation(meta.customData, {
				type: "mark",
				index1Based: index,
				status
			});
		} else return c.json({
			ok: false,
			error: "Invalid op (add|remove|mark|reset)"
		}, 400);
		if (mutation.kind === "error") return c.json({
			ok: false,
			error: mutation.error
		}, 400);
		if (mutation.kind === "noop") {
			const persistentGoal = readPersistentGoal(meta.customData);
			return c.json({
				ok: true,
				sessionKey,
				noop: true,
				message: mutation.message,
				persistentGoal
			});
		}
		const uiLocale = normalizeGoalUiLocale(body.uiLocale);
		const customData = uiLocale != null ? mergePersistentGoalUiLocale(mutation.customData, uiLocale) ?? mutation.customData : mutation.customData;
		await sm.updateSessionMetadata(sessionKey, { customData });
		const persistentGoal = readPersistentGoal((await sm.getSessionMetadata(sessionKey))?.customData);
		return c.json({
			ok: true,
			sessionKey,
			op,
			persistentGoal
		});
	});
}
//#endregion
export { registerGoalsRoutes };

//# sourceMappingURL=goals.js.map