import { randomUUID } from "node:crypto";
import { AgentState } from "./state.js";

export const EXECUTION_LEASE_NAME = "wallet-execution";

export class ExecutionLease {
  private readonly owner = randomUUID();
  private heartbeat: NodeJS.Timeout | null = null;
  private lost = false;

  constructor(
    private readonly stateDbPath: string,
    private readonly ttlMs = 300_000,
  ) {}

  acquire() {
    const state = new AgentState(this.stateDbPath);
    const acquired = state.acquireRuntimeLock(EXECUTION_LEASE_NAME, this.owner, this.ttlMs);
    state.close();
    if (!acquired) return false;
    this.heartbeat = setInterval(() => {
      try {
        const heartbeatState = new AgentState(this.stateDbPath);
        const renewed = heartbeatState.renewRuntimeLock(EXECUTION_LEASE_NAME, this.owner, this.ttlMs);
        heartbeatState.close();
        if (!renewed) this.lost = true;
      } catch {
        this.lost = true;
      }
    }, Math.min(60_000, Math.floor(this.ttlMs / 3)));
    this.heartbeat.unref();
    return true;
  }

  assertActive() {
    if (this.lost) throw new Error("Wallet execution lease was lost");
  }

  release() {
    if (this.heartbeat) clearInterval(this.heartbeat);
    this.heartbeat = null;
    const state = new AgentState(this.stateDbPath);
    state.releaseRuntimeLock(EXECUTION_LEASE_NAME, this.owner);
    state.close();
  }
}
