export function makeClaimDb(db) {
    return {
        async claimOneAvailable(addr, version, nowIso) {
            // Query builder (NOT raw sql) so the reactor's namespaced Kysely
            // schema-qualifies `environments`.
            const row = (await db
                .updateTable("environments")
                .set({ poolState: "CLAIMED", claimedBy: addr, claimedAt: nowIso })
                .where("id", "=", db
                .selectFrom("environments")
                .select("id")
                .where("poolState", "=", "AVAILABLE")
                .where("status", "=", "READY")
                .where("pinnedVersion", "=", version)
                .orderBy("id")
                .limit(1)
                .forUpdate()
                .skipLocked())
                .returning(["id", "tenantId", "subdomain", "poolState"])
                .executeTakeFirst());
            return row ?? null;
        },
    };
}
/** Keeper-side helpers over the shared `environments` table. */
export function makeKeeperDb(db) {
    return {
        async listPoolRows() {
            return (await db
                .selectFrom("environments")
                .select(["id", "poolState", "pinnedVersion", "status"])
                .where("poolState", "in", ["WARMING", "AVAILABLE", "CLAIMED", "FAILED"])
                .execute());
        },
        async seedWarming(input) {
            // New docs insert cleanly. The onConflict guard only (re)sets poolState
            // when it is currently NULL (e.g. re-adopting a cleared env) — it never
            // clobbers a WARMING/AVAILABLE/CLAIMED row.
            await db
                .insertInto("environments")
                .values({
                id: input.id,
                subdomain: input.subdomain,
                tenantId: input.tenantId,
                poolState: "WARMING",
                pinnedVersion: input.pinnedVersion,
            })
                .onConflict((oc) => oc
                .column("id")
                .doUpdateSet({
                poolState: "WARMING",
                pinnedVersion: input.pinnedVersion,
            })
                .where("environments.poolState", "is", null))
                .execute();
        },
        async promoteReadyToAvailable() {
            await db
                .updateTable("environments")
                .set({ poolState: "AVAILABLE" })
                .where("poolState", "=", "WARMING")
                .where("status", "=", "READY")
                .execute();
        },
        async clearPoolState(ids) {
            if (ids.length === 0)
                return;
            await db
                .updateTable("environments")
                .set({ poolState: null })
                .where("id", "in", ids)
                .execute();
        },
    };
}
