/**
 * gemini-catalog.js — SF-side cache writer for gemini-cli model discovery.
 *
 * The OAuth + Code Assist plumbing lives in the dedicated
 * @singularity-forge/google-gemini-cli-provider package (where the rest of the
 * gemini-cli-core integration is centralized). This module only handles the
 * SF-specific concerns: where on disk to cache the result, how often to
 * refresh, and the session_start lifecycle hook.
 *
 * Why a separate cache from the generic model-catalog-cache: that cache is
 * keyed off providers with REST /v1/models and API-key auth. google-gemini-cli
 * has neither — it uses OAuth via gemini-cli-core and surfaces models implicit
 * in the per-model quota table. Cache file shape stays compatible with
 * model-catalog-cache.getKnownModelIds so consumers read both transparently.
 */
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { sfRuntimeRoot } from "./paths.js";

const GEMINI_CLI_PROVIDER_ID = "google-gemini-cli";
const CATALOG_TTL_MS = 6 * 60 * 60 * 1000;

function cacheFilePath(basePath) {
	return join(
		sfRuntimeRoot(basePath),
		"model-catalog",
		`${GEMINI_CLI_PROVIDER_ID}.json`,
	);
}

function isCacheFresh(basePath) {
	try {
		const path = cacheFilePath(basePath);
		if (!existsSync(path)) return false;
		const entry = JSON.parse(readFileSync(path, "utf-8"));
		if (!entry?.fetchedAt || !Array.isArray(entry.modelIds)) return false;
		return Date.now() - new Date(entry.fetchedAt).getTime() <= CATALOG_TTL_MS;
	} catch {
		return false;
	}
}

function writeCacheEntry(basePath, modelIds) {
	try {
		mkdirSync(join(sfRuntimeRoot(basePath), "model-catalog"), {
			recursive: true,
		});
		writeFileSync(
			cacheFilePath(basePath),
			JSON.stringify({
				fetchedAt: new Date().toISOString(),
				modelIds,
			}),
			"utf-8",
		);
	} catch {
		// Best-effort — never fail the caller.
	}
}

/**
 * Discover and cache the gemini-cli model list. Returns the model IDs on
 * success, null on any failure.
 *
 * Consumer: scheduleGeminiCatalogRefresh during session_start.
 */
export async function refreshGeminiCatalog(basePath) {
	try {
		const { discoverGeminiCliModels } = await import(
			"@singularity-forge/google-gemini-cli-provider"
		);
		const modelIds = await discoverGeminiCliModels(basePath);
		if (!modelIds || modelIds.length === 0) return null;
		writeCacheEntry(basePath, modelIds);
		return modelIds;
	} catch {
		return null;
	}
}

/**
 * Fire-and-forget background refresh of the gemini-cli model catalog. Skipped
 * if the on-disk cache is already fresh (within CATALOG_TTL_MS).
 *
 * Consumer: bootstrap/register-hooks.js session_start hook.
 */
export function scheduleGeminiCatalogRefresh(basePath) {
	if (isCacheFresh(basePath)) return;
	setImmediate(async () => {
		try {
			await refreshGeminiCatalog(basePath);
		} catch {
			// Per-provider failure is silently swallowed.
		}
	});
}
