/**
 * sf-db/sf-db-md-tracker.js — DB adapter for tracked_md_files.
 *
 * Purpose: persist sha256 observations for source-of-truth markdown files so
 * SF can detect external edits (hand-edits, git pulls, cross-agent edits) on
 * the next session start.
 *
 * Consumer: md-file-tracker.js — called from bootstrap/register-hooks.js on
 * session_start.
 */
import { _getAdapter } from "./sf-db-core.js";

/**
 * Upsert a file observation row. Called after hashing the file on session
 * start, both for new files and for files whose sha has changed.
 *
 * Purpose: record "SF last saw this file with this hash at this commit" so
 * the next session can detect drift.
 *
 * Consumer: md-file-tracker.js observeMdFiles().
 */
export function upsertTrackedMdFile({
	relpath,
	sha256,
	sizeBytes,
	lastSeenCommit,
	category,
}) {
	const db = _getAdapter();
	if (!db) return;
	db.prepare(`
		INSERT INTO tracked_md_files (relpath, sha256, size_bytes, last_seen_at, last_seen_commit, category, active)
		VALUES (:relpath, :sha256, :size_bytes, :last_seen_at, :last_seen_commit, :category, 1)
		ON CONFLICT(relpath) DO UPDATE SET
			sha256           = excluded.sha256,
			size_bytes       = excluded.size_bytes,
			last_seen_at     = excluded.last_seen_at,
			last_seen_commit = excluded.last_seen_commit,
			category         = excluded.category,
			active           = 1
	`).run({
		":relpath": relpath,
		":sha256": sha256,
		":size_bytes": sizeBytes,
		":last_seen_at": new Date().toISOString(),
		":last_seen_commit": lastSeenCommit ?? null,
		":category": category ?? "meta",
	});
}

/**
 * Return the tracked row for a repo-relative path, or null if untracked.
 *
 * Purpose: retrieve the last-seen sha so the tracker can detect drift.
 *
 * Consumer: md-file-tracker.js detectMdFileDrift().
 */
export function getTrackedMdFile(relpath) {
	const db = _getAdapter();
	if (!db) return null;
	return (
		db
			.prepare(
				"SELECT * FROM tracked_md_files WHERE relpath = :relpath AND active = 1",
			)
			.get({ ":relpath": relpath }) ?? null
	);
}

/**
 * Mark a tracked file inactive (e.g. deleted from disk).
 * Does not purge the row — that requires explicit operator confirmation.
 *
 * Purpose: distinguish "file gone" from "never seen" without data loss.
 *
 * Consumer: md-file-tracker.js on file-not-found during walk.
 */
export function deactivateTrackedMdFile(relpath) {
	const db = _getAdapter();
	if (!db) return;
	db.prepare(
		"UPDATE tracked_md_files SET active = 0 WHERE relpath = :relpath",
	).run({ ":relpath": relpath });
}

/**
 * Return all active tracked rows. Used during session start to find files that
 * were tracked in a previous session but are no longer present on disk.
 *
 * Purpose: detect deletions that occurred between sessions.
 *
 * Consumer: md-file-tracker.js detectMdFileDrift().
 */
export function getAllTrackedMdFiles() {
	const db = _getAdapter();
	if (!db) return [];
	return db
		.prepare("SELECT * FROM tracked_md_files WHERE active = 1 ORDER BY relpath")
		.all();
}
