import { getErrorMessage } from "../error-utils.js";
import { getDatabase, getDbPath, insertLlmTaskOutcome } from "../sf-db.js";
import { logWarning } from "../workflow-logger.js";
import { createBeforeModelSelectHandler } from "./hook-handler.mjs";
import { loadCapabilityOverrides } from "./loadCapabilityOverrides.mjs";
import { validateOutcome } from "./outcome-recorder.mjs";

const DEFAULT_N_PRIOR = 10;
const DEFAULT_ROLLING_DAYS = 30;
const DEFAULT_UCB_C = 1.4;
let cachedHandler = null;
let cachedDbPath = null;
let cachedDb = null;
let initPromise = null;
async function ensureLearningReady() {
	const db = getDatabase();
	const dbPath = getDbPath();
	if (!db || !dbPath) {
		cachedHandler = null;
		cachedDbPath = null;
		cachedDb = null;
		return;
	}
	if (cachedHandler && cachedDbPath === dbPath && cachedDb === db) return;
	if (initPromise) return initPromise;
	initPromise = (async () => {
		try {
			const priors = await loadCapabilityOverrides();
			cachedHandler = createBeforeModelSelectHandler({
				db,
				overrides: priors.overrides,
				weights: priors.weights,
				benchmarks: priors.benchmarks,
				opts: {
					nPrior: DEFAULT_N_PRIOR,
					rollingDays: DEFAULT_ROLLING_DAYS,
					ucbC: DEFAULT_UCB_C,
					explorationEnabled: true,
				},
			});
			cachedDbPath = dbPath;
			cachedDb = db;
		} catch (err) {
			cachedHandler = null;
			cachedDbPath = null;
			cachedDb = null;
			logWarning(
				"dispatch",
				`failed to initialize learned routing: ${getErrorMessage(err)}`,
			);
		} finally {
			initPromise = null;
		}
	})();
	return initPromise;
}
export async function initializeLearningRuntime() {
	await ensureLearningReady();
}
export function resetLearningRuntime() {
	cachedHandler = null;
	cachedDbPath = null;
	cachedDb = null;
	initPromise = null;
}
export async function selectLearnedModel(input) {
	await ensureLearningReady();
	if (!cachedHandler) return undefined;
	return cachedHandler(input);
}
export function recordLearnedOutcome(input) {
	const validation = validateOutcome(input);
	if (!validation.valid) return false;
	try {
		return insertLlmTaskOutcome(input);
	} catch (err) {
		logWarning(
			"db",
			`failed to record learned routing outcome: ${getErrorMessage(err)}`,
		);
		return false;
	}
}
