'use strict';

// Fallback policy for a PERIODIC, HEAVY, idempotent db-owner-worker job (a backfill or
// import sweep) when its worker op fails. The hard rule this enforces: a slow/degraded/
// timed-out worker must NEVER cause the heavy sweep to run on the main event loop — that
// turns transient worker saturation into a multi-second UI freeze (a giant transcript
// ingest holds the SQLite write lock → the backfill op times out → its .catch() ran the
// whole JSON.parse + row-rewrite on main). These jobs are idempotent and re-run on the
// next scheduler tick once the worker recovers, so "skip this tick" is correct.
//
// The ONE case where the in-process owner queue IS the intended path is a genuinely
// DISABLED worker (feature off by config, CTM_DB_OWNER_WORKER_DISABLED): then there is no
// worker to contend with and in-process is how writes are meant to run.
//
// Pure + dependency-injected (runInProcess, logDropped) so it is unit-testable in isolation
// from server.js. Mirrors the _runBestEffortWorkerOpOrDrop policy but returns a skip result
// the scheduler tolerates instead of a fire-and-forget drop.

const WORKER_DISABLED_CODE = 'CTM_DB_OWNER_WORKER_DISABLED';

function makeSkipHeavyWorkerJobOnDegraded({ runInProcess, logDropped } = {}) {
  if (typeof runInProcess !== 'function') {
    throw new Error('makeSkipHeavyWorkerJobOnDegraded requires a runInProcess function');
  }
  // Returns a factory: (label, skipResult, inProcessFn) → a .catch() handler.
  // skipResult may be a value or a thunk (evaluated lazily on the skip path).
  return function skipHeavyWorkerJobOnDegraded(label, skipResult, inProcessFn) {
    return (workerError) => {
      if (workerError && workerError.code === WORKER_DISABLED_CODE) {
        return runInProcess(label, inProcessFn);
      }
      if (typeof logDropped === 'function') logDropped(label, workerError);
      return Promise.resolve(typeof skipResult === 'function' ? skipResult() : skipResult);
    };
  };
}

module.exports = { makeSkipHeavyWorkerJobOnDegraded, WORKER_DISABLED_CODE };
