// src/engine/reflection/user-lock.ts
import lockfile from 'proper-lockfile';
import { join } from 'path';
import { mkdirSync, existsSync, writeFileSync } from 'fs';

export interface WithUserLockOpts {
  timeoutMs?: number; // default 5000
  retries?: number;   // default 30 (with 50-200ms backoff)
}

export async function withUserLock<T>(
  dataDir: string,
  userId: string,
  fn: () => Promise<T>,
  opts: WithUserLockOpts = {}
): Promise<T> {
  const userDir = join(dataDir, userId);
  if (!existsSync(userDir)) mkdirSync(userDir, { recursive: true });
  const sentinel = join(userDir, '.reflection.lock');
  if (!existsSync(sentinel)) writeFileSync(sentinel, '');

  const release = await lockfile.lock(sentinel, {
    retries: {
      retries: opts.retries ?? 30,
      minTimeout: 50, maxTimeout: 200, factor: 1.5,
    },
    stale: opts.timeoutMs ?? 5000,
  });
  try {
    return await fn();
  } finally {
    await release();
  }
}
