/**
 * Service Tier — gating, status formatting, icon resolution, and
 * the /fast command handler.
 *
 * Service tiers (priority/flex) are an OpenAI feature that only applies
 * to gpt-5.4 variants. This module centralizes the model-gating logic
 * so that icons, preferences, and the before_provider_request hook all
 * use a single source of truth.
 */
import { existsSync, readFileSync } from "node:fs";
import {
	ensurePreferencesFile,
	serializePreferencesToFrontmatter,
} from "./commands-prefs-wizard.js";
import { saveFile } from "./files.js";
import {
	getGlobalSFPreferencesPath,
	loadEffectiveSFPreferences,
	loadGlobalSFPreferences,
} from "./preferences.js";

const SERVICE_TIER_SCOPE_NOTE =
	"Only affects gpt-5.4 models, regardless of provider.";
// ─── Gating ──────────────────────────────────────────────────────────────────
/**
 * Model ID prefixes (bare, without provider) that support OpenAI service tiers.
 *
 * This list is the fallback for callers that only have a model ID string.
 * The authoritative source of truth is `model.capabilities.supportsServiceTier`
 * (set via CAPABILITY_PATCHES in packages/ai/src/models.ts). When callers
 * have access to the full Model object, prefer reading capabilities directly.
 *
 * GPT-5.5 is intentionally excluded until we verify its provider payload
 * contract instead of assuming `service_tier` support.
 *
 * See: https://github.com/singularity-forge/sf-run/issues/2546
 */
const SERVICE_TIER_MODEL_PREFIXES = ["gpt-5.4"];
/**
 * Returns true when the given model ID supports OpenAI service tiers.
 * Reads from SERVICE_TIER_MODEL_PREFIXES — update that list, not this function.
 */
export function supportsServiceTier(modelId) {
	if (!modelId) return false;
	// Strip provider prefix if present (e.g. "openai/gpt-5.4" → "gpt-5.4")
	const bare = modelId.includes("/") ? modelId.split("/").pop() : modelId;
	return SERVICE_TIER_MODEL_PREFIXES.some((prefix) => bare.startsWith(prefix));
}
// ─── Status Formatting ───────────────────────────────────────────────────────
/**
 * Human-readable description of the current service tier setting.
 */
export function formatServiceTierStatus(tier) {
	if (!tier) {
		const explicitlyDisabled = isServiceTierDisabled();
		const header = explicitlyDisabled
			? 'Service tier: disabled (service_tier: "off" in preferences)'
			: "Service tier: disabled";
		return [
			header,
			"",
			"Usage:",
			"  /fast on     Set to priority (2x cost, faster)",
			"  /fast flex   Set to flex (0.5x cost, slower)",
			"  /fast off    Disable service tier",
			"",
			SERVICE_TIER_SCOPE_NOTE,
		].join("\n");
	}
	const label =
		tier === "priority"
			? "priority (2x cost, faster)"
			: "flex (0.5x cost, slower)";
	return [
		`Service tier: ${label}`,
		"",
		"Usage:",
		"  /fast on     Set to priority (2x cost, faster)",
		"  /fast flex   Set to flex (0.5x cost, slower)",
		"  /fast off    Disable service tier",
		"",
		SERVICE_TIER_SCOPE_NOTE,
	].join("\n");
}
export function formatServiceTierFooterStatus(tier, modelId) {
	if (!tier || !modelId || !supportsServiceTier(modelId)) return undefined;
	return tier === "priority" ? "fast: ⚡ priority" : "fast: 💰 flex";
}
// ─── Icon Resolution ─────────────────────────────────────────────────────────
/**
 * Returns the appropriate icon for the active service tier and model.
 * Returns empty string when the tier is inactive or the model doesn't
 * support service tiers.
 */
export function resolveServiceTierIcon(tier, modelId) {
	if (!tier || !supportsServiceTier(modelId)) return "";
	return tier === "priority" ? "⚡" : "💰";
}
// ─── Preference Read ─────────────────────────────────────────────────────────
/**
 * Read the effective service_tier setting from preferences.
 * Returns undefined for both "explicitly disabled" (`"off"`) and "not
 * configured"; callers that need to distinguish the two should use
 * {@link isServiceTierDisabled}.
 */
export function getEffectiveServiceTier() {
	const prefs = loadEffectiveSFPreferences()?.preferences;
	const raw = prefs?.service_tier;
	if (raw === "priority" || raw === "flex") return raw;
	return undefined;
}
/**
 * True when the user has explicitly set `service_tier: "off"` in preferences.
 * Callers that register UI/hooks for the feature should skip registration
 * entirely in this case — not just no-op their behavior. That keeps the
 * feature fully dormant on setups that will never run a gpt-5.4 model.
 */
export function isServiceTierDisabled() {
	const prefs = loadEffectiveSFPreferences()?.preferences;
	return prefs?.service_tier === "off";
}
// ─── Preference Write ────────────────────────────────────────────────────────
function extractBodyAfterFrontmatter(content) {
	const start = content.startsWith("---\n")
		? 4
		: content.startsWith("---\r\n")
			? 5
			: -1;
	if (start === -1) return null;
	const closingIdx = content.indexOf("\n---", start);
	if (closingIdx === -1) return null;
	const after = content.slice(closingIdx + 4);
	return after.trim() ? after : null;
}
async function writeGlobalServiceTier(ctx, tier) {
	const path = getGlobalSFPreferencesPath();
	await ensurePreferencesFile(path, ctx, "global");
	const existing = loadGlobalSFPreferences();
	const prefs = existing?.preferences ? { ...existing.preferences } : {};
	prefs.version = prefs.version || 1;
	if (tier) {
		prefs.service_tier = tier;
	} else {
		delete prefs.service_tier;
	}
	const frontmatter = serializePreferencesToFrontmatter(prefs);
	let body =
		"\n# SF Skill Preferences\n\nSee `~/.sf/agent/extensions/sf/docs/preferences-reference.md` for full field documentation and examples.\n";
	if (existsSync(path)) {
		const preserved = extractBodyAfterFrontmatter(readFileSync(path, "utf-8"));
		if (preserved) body = preserved;
	}
	await saveFile(path, `---\n${frontmatter}---${body}`);
	await ctx.waitForIdle();
	await ctx.reload();
}
// ─── Command Handler ─────────────────────────────────────────────────────────
/**
 * Handle `/fast [on|off|flex|status]`.
 */
export async function handleFast(args, ctx) {
	const trimmed = args.trim().toLowerCase();
	if (!trimmed || trimmed === "status") {
		const tier = getEffectiveServiceTier();
		ctx.ui.notify(formatServiceTierStatus(tier), "info");
		return;
	}
	if (trimmed === "on" || trimmed === "flex") {
		if (isServiceTierDisabled()) {
			ctx.ui.notify(
				'Service tier is explicitly disabled (service_tier: "off" in preferences). Remove that line before enabling.',
				"warning",
			);
			return;
		}
		const nextTier = trimmed === "on" ? "priority" : "flex";
		await writeGlobalServiceTier(ctx, nextTier);
		ctx.ui.setStatus(
			"sf-fast",
			formatServiceTierFooterStatus(nextTier, ctx.model?.id),
		);
		const label =
			nextTier === "priority"
				? "priority (2x cost, faster responses)"
				: "flex (0.5x cost, slower responses)";
		ctx.ui.notify(
			`Service tier set to ${label}. Only affects gpt-5.4 models, regardless of provider.`,
			"info",
		);
		return;
	}
	if (trimmed === "off") {
		await writeGlobalServiceTier(ctx, undefined);
		ctx.ui.setStatus("sf-fast", undefined);
		ctx.ui.notify("Service tier disabled.", "info");
		return;
	}
	ctx.ui.notify(
		"Usage: /fast [on|off|flex|status]\n\n  on    Priority tier (2x cost, faster)\n  off   Disable service tier\n  flex  Flex tier (0.5x cost, slower)\n  status Show current setting",
		"warning",
	);
}
