export const KIT_TASK_STATE_PROJECTION_META_TABLE = "kit_task_state_projection_meta";
/** Row schema version for JSON/API surfaces (distinct from kit SQLite user_version). */
export const TASK_STATE_PROJECTION_META_SCHEMA_VERSION = 1;
export const TASK_STATE_PROJECTION_SYNC_STATUSES = [
    "empty",
    "fresh",
    "stale",
    "rebuilding",
    "corrupt"
];
/** Canonical event-log backend the local SQLite cache is projecting from. */
export const TASK_STATE_PROJECTION_BACKENDS = ["git-event-log", "sqlite-relational"];
const SYNC_STATUS_SET = new Set(TASK_STATE_PROJECTION_SYNC_STATUSES);
const BACKEND_SET = new Set(TASK_STATE_PROJECTION_BACKENDS);
function tableExists(db, name) {
    const row = db
        .prepare("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?")
        .get(name);
    return Boolean(row);
}
export function taskStateProjectionMetaTableAvailable(db) {
    return tableExists(db, KIT_TASK_STATE_PROJECTION_META_TABLE);
}
function parseSyncStatus(raw) {
    const value = typeof raw === "string" ? raw.trim() : "";
    return SYNC_STATUS_SET.has(value) ? value : "empty";
}
function parseBackend(raw) {
    const value = typeof raw === "string" ? raw.trim() : "";
    return BACKEND_SET.has(value) ? value : "git-event-log";
}
export function readTaskStateProjectionMeta(db) {
    if (!taskStateProjectionMetaTableAvailable(db)) {
        return null;
    }
    const row = db
        .prepare(`SELECT backend, applied_sequence, source_commit, projection_schema_version, sync_status, updated_at
       FROM ${KIT_TASK_STATE_PROJECTION_META_TABLE} WHERE id = 1`)
        .get();
    if (!row) {
        return null;
    }
    return {
        schemaVersion: TASK_STATE_PROJECTION_META_SCHEMA_VERSION,
        backend: parseBackend(row.backend),
        appliedSequence: Number(row.applied_sequence) || 0,
        sourceCommit: typeof row.source_commit === "string" && row.source_commit.trim() ? row.source_commit.trim() : null,
        projectionSchemaVersion: Number(row.projection_schema_version) || 1,
        syncStatus: parseSyncStatus(row.sync_status),
        updatedAt: row.updated_at
    };
}
export function upsertTaskStateProjectionMeta(db, input) {
    if (!taskStateProjectionMetaTableAvailable(db)) {
        throw new Error(`${KIT_TASK_STATE_PROJECTION_META_TABLE} is not available (kit SQLite user_version < 28)`);
    }
    const existing = readTaskStateProjectionMeta(db);
    const next = {
        schemaVersion: TASK_STATE_PROJECTION_META_SCHEMA_VERSION,
        backend: input.backend ?? existing?.backend ?? "git-event-log",
        appliedSequence: input.appliedSequence ?? existing?.appliedSequence ?? 0,
        sourceCommit: input.sourceCommit !== undefined ? input.sourceCommit : (existing?.sourceCommit ?? null),
        projectionSchemaVersion: input.projectionSchemaVersion ?? existing?.projectionSchemaVersion ?? 1,
        syncStatus: input.syncStatus ?? existing?.syncStatus ?? "empty",
        updatedAt: input.updatedAt
    };
    db.prepare(`INSERT INTO ${KIT_TASK_STATE_PROJECTION_META_TABLE} (
       id, backend, applied_sequence, source_commit, projection_schema_version, sync_status, updated_at
     ) VALUES (1, @backend, @applied_sequence, @source_commit, @projection_schema_version, @sync_status, @updated_at)
     ON CONFLICT(id) DO UPDATE SET
       backend = excluded.backend,
       applied_sequence = excluded.applied_sequence,
       source_commit = excluded.source_commit,
       projection_schema_version = excluded.projection_schema_version,
       sync_status = excluded.sync_status,
       updated_at = excluded.updated_at`).run({
        backend: next.backend,
        applied_sequence: next.appliedSequence,
        source_commit: next.sourceCommit,
        projection_schema_version: next.projectionSchemaVersion,
        sync_status: next.syncStatus,
        updated_at: next.updatedAt
    });
    return next;
}
