/**
 * SF Health Widget — always-on ambient health signal rendered belowEditor.
 *
 * Shows a compact 1-2 line summary: progress score, budget, provider key
 * status, and doctor/environment issue count. Refreshes every 60 seconds.
 * Quiet when everything is healthy; turns amber/red when issues arise.
 *
 * Widget key: "sf-health", placement: "belowEditor"
 */
import { isRemoteConfigured } from "../remote-questions/manager.js";
import { projectRoot } from "./commands/context.js";
import { runEnvironmentChecks } from "./doctor-environment.js";
import {
	runProviderChecks,
	summariseProviderIssues,
} from "./doctor-providers.js";
import {
	buildHealthLines,
	detectHealthWidgetProjectState,
} from "./health-widget-core.js";
import { getProjectTotals, loadLedgerFromDisk } from "./metrics.js";
import {
	nativeCommitSubject,
	nativeGetCurrentBranch,
	nativeIsRepo,
	nativeLastCommitEpoch,
} from "./native-git-bridge.js";
import { loadEffectiveSFPreferences } from "./preferences.js";
import { safeSetWidget } from "./widget-safe.js";

// ── Data loader ────────────────────────────────────────────────────────────────
function loadHealthWidgetData(basePath) {
	let budgetCeiling;
	let budgetSpent = 0;
	let providerIssue = null;
	let environmentErrorCount = 0;
	let environmentWarningCount = 0;
	let lastCommitEpoch = null;
	let lastCommitMessage = null;
	const projectState = detectHealthWidgetProjectState(basePath);
	try {
		const prefs = loadEffectiveSFPreferences();
		budgetCeiling = prefs?.preferences?.budget_ceiling;
		const ledger = loadLedgerFromDisk(basePath);
		if (ledger) {
			const totals = getProjectTotals(ledger.units ?? []);
			budgetSpent = totals.cost;
		}
	} catch {
		/* non-fatal */
	}
	try {
		const providerResults = runProviderChecks();
		providerIssue = summariseProviderIssues(providerResults);
	} catch {
		/* non-fatal */
	}
	try {
		const envResults = runEnvironmentChecks(basePath);
		for (const r of envResults) {
			if (r.status === "error") environmentErrorCount++;
			else if (r.status === "warning") environmentWarningCount++;
		}
	} catch {
		/* non-fatal */
	}
	// ── Last commit info ──
	try {
		if (nativeIsRepo(basePath)) {
			const branch = nativeGetCurrentBranch(basePath);
			const epoch = nativeLastCommitEpoch(basePath, branch || "HEAD");
			if (epoch > 0) {
				lastCommitEpoch = epoch;
				lastCommitMessage =
					nativeCommitSubject(basePath, branch || "HEAD") || null;
			}
		}
	} catch {
		/* non-fatal */
	}
	return {
		projectState,
		budgetCeiling,
		budgetSpent,
		providerIssue,
		environmentErrorCount,
		environmentWarningCount,
		lastCommitEpoch,
		lastCommitMessage,
		lastRefreshed: Date.now(),
		remoteQuestionsConfigured: isRemoteConfigured(),
	};
}
// ── Widget init ────────────────────────────────────────────────────────────────
const REFRESH_INTERVAL_MS = 60_000;

/**
 * Initialize the always-on sf-health widget (belowEditor).
 * Call once from the extension entry point after context is available.
 */
export function initHealthWidget(ctx) {
	if (!ctx.hasUI) return;
	const basePath = projectRoot();
	const initialData = loadHealthWidgetData(basePath);

	// String-array fallback — used in RPC mode (factory is a no-op there).
	// The factory call below overwrites this when the host supports factories.
	safeSetWidget(ctx, "sf-health", buildHealthLines(initialData), {
		placement: "belowEditor",
	});

	// Factory-based widget for TUI mode — replaces the string-array above.
	safeSetWidget(
		ctx,
		"sf-health",
		(_tui, _theme) => {
			let data = initialData;
			let cachedLines;
			let refreshInFlight = false;
			const refresh = async () => {
				if (refreshInFlight) return;
				refreshInFlight = true;
				try {
					data = loadHealthWidgetData(basePath);
					cachedLines = undefined;
					_tui.requestRender();
				} catch {
					/* non-fatal */
				} finally {
					refreshInFlight = false;
				}
			};
			// Fire first enrichment immediately. requestRender() inside is a no-op
			// if the widget has not yet rendered, so this is safe before factory return.
			void refresh();
			const refreshTimer = setInterval(() => {
				void refresh();
			}, REFRESH_INTERVAL_MS);
			return {
				render(_width) {
					if (!cachedLines) cachedLines = buildHealthLines(data);
					return cachedLines;
				},
				invalidate() {
					cachedLines = undefined;
				},
				dispose() {
					clearInterval(refreshTimer);
				},
			};
		},
		{ placement: "belowEditor" },
	);
}
