function createLaterAndStart({ todayWork, todaySync, laterWork, refresh, warm, start, announce }) {
  const pending = new Map();

  async function run(item, identity) {
    const added = todayWork.add(item);
    if (added === 'full') {
      announce('Today is limited to 5 items. Remove one, then try Start now again.');
      return 'full';
    }
    if (added !== 'added' && added !== 'exists') {
      announce('Could not save Today on this device. The item remains in Later; try again.');
      return added;
    }
    if (added === 'added' && !todaySync.enqueue('add', identity)) {
      todayWork.remove(item);
      announce('Today sync is unavailable. The item remains in Later; try again.');
      return 'sync-unavailable';
    }
    if (!laterWork.restore(item)) {
      if (added === 'added') {
        todayWork.remove(item);
        todaySync.enqueue('remove', identity);
        todaySync.flush();
      }
      announce('Could not remove this item from Later. Nothing was started; try again.');
      return 'later-unavailable';
    }
    refresh();
    if (added === 'added') todaySync.flush();
    warm();
    const outcome = await start(item);
    if (outcome === 'gated') {
      announce('Moved to Today. Choose how to handle its blocker before starting.');
      return 'gated';
    }
    announce(added === 'exists' ? 'Opened the existing Today item.' : 'Moved to Today and opened.');
    return 'started';
  }

  function startDeferred(item) {
    const identity = todayWork.identity(item);
    if (pending.has(identity)) return pending.get(identity);
    const operation = run(item, identity).finally(() => pending.delete(identity));
    pending.set(identity, operation);
    return operation;
  }

  return { start: startDeferred };
}

if (typeof module !== 'undefined' && module.exports) module.exports = createLaterAndStart;
