function createLaterSync({ storage, getLogin, fetchJson, onRemoteRecords, onStatus, createOperationId, createChannel, coordinator,
  setTimer = globalThis.setTimeout, clearTimer = globalThis.clearTimeout, retryBaseMs = 1000, retryMaxMs = 30000,
  now = Date.now, maxOfflineMs = 30 * 24 * 60 * 60 * 1000 }) {
  const prefix = 'stackchain.later-sync.v1.';
  const migrationPrefix = 'stackchain.later-sync-migrated.v1.';
  const snapshotPrefix = 'stackchain.later-sync-snapshot.v1.';
  let flushing = null;
  let channel = null;
  let channelKey = '';
  let retryTimer = null;
  let retryAttempt = 0;
  let expiredCount = 0;
  const knownOperationKeys = new Set();

  function cancelRetry() {
    if (retryTimer !== null) clearTimer?.(retryTimer);
    retryTimer = null;
  }

  function scheduleRetry(error, ownerKey) {
    if (retryTimer !== null || !pending().length || !ownerKey) return;
    const advised = Number(error?.retryAfter);
    const delayMs = Number.isFinite(advised) && advised >= 0
      ? advised * 1000
      : Math.min(retryMaxMs, retryBaseMs * (2 ** retryAttempt));
    retryAttempt += 1;
    onStatus?.('retrying', { delayMs });
    retryTimer = setTimer?.(async () => {
      retryTimer = null;
      if (key() !== ownerKey) return false;
      return flush();
    }, delayMs);
    retryTimer?.unref?.();
  }

  function key() {
    const login = String(getLogin?.() || '').trim().toLowerCase();
    return login ? prefix + encodeURIComponent(login) : '';
  }

  function snapshotKey() {
    const storageKey = key();
    return storageKey ? snapshotPrefix + storageKey.slice(prefix.length) : '';
  }

  function savedRevision() {
    try {
      const snapshot = JSON.parse(storage?.getItem(snapshotKey()) || 'null');
      return Number.isInteger(snapshot?.revision) ? snapshot.revision : -1;
    } catch (_error) {
      return -1;
    }
  }

  function validRecords(records) {
    return records && typeof records === 'object' && !Array.isArray(records);
  }

  function adopt(plan, broadcast = true) {
    if (!Number.isInteger(plan?.revision) || !validRecords(plan?.records)) return false;
    if (plan.revision < savedRevision()) return false;
    const snapshot = { revision: plan.revision, records: plan.records };
    try {
      storage?.setItem(snapshotKey(), JSON.stringify(snapshot));
    } catch (_error) {
      // Server truth remains usable in this tab when storage is unavailable.
    }
    onRemoteRecords?.(plan.records);
    if (broadcast) channel?.postMessage(snapshot);
    return true;
  }

  function ensureChannel() {
    const storageKey = key();
    if (!storageKey || channelKey === storageKey) return;
    channel?.close?.();
    const factory = createChannel || (globalThis.window?.BroadcastChannel
      ? name => new globalThis.window.BroadcastChannel(name)
      : null);
    channelKey = storageKey;
    channel = factory?.('stackchain-later-' + storageKey.slice(prefix.length)) || null;
    channel?.addEventListener?.('message', event => {
      if (key() === storageKey) adopt(event.data, false);
    });
  }

  function pending() {
    const storageKey = key();
    if (!storageKey || !storage) return [];
    const recordPrefix = storageKey + '.operation.';
    try {
      const legacy = JSON.parse(storage.getItem(storageKey) || '[]');
      if (Array.isArray(legacy)) {
        legacy.forEach((operation, index) => {
          if (!operation?.operation_id) return;
          const recordKey = recordPrefix + encodeURIComponent(operation.operation_id);
          storage.setItem(recordKey, JSON.stringify({ operation, queued_at: index }));
          knownOperationKeys.add(recordKey);
        });
        if (legacy.length) storage.removeItem(storageKey);
      }
      const keys = new Set([...knownOperationKeys].filter(candidate => candidate.startsWith(recordPrefix)));
      for (let index = 0; index < Number(storage.length || 0); index += 1) {
        const candidate = storage.key?.(index);
        if (candidate?.startsWith(recordPrefix)) keys.add(candidate);
      }
      const records = [...keys].map(recordKey => {
        const record = JSON.parse(storage.getItem(recordKey) || 'null');
        return record ? { ...record, recordKey } : null;
      }).filter(record => record?.operation);
      const expired = records.filter(record => Number(record.queued_at) >= 1_000_000_000_000 &&
        now() - Number(record.queued_at) > maxOfflineMs);
      expired.forEach(record => {
        storage.removeItem(record.recordKey);
        knownOperationKeys.delete(record.recordKey);
      });
      if (expired.length) {
        expiredCount += expired.length;
        onStatus?.('expired', { count: expiredCount });
      }
      const activeRecords = records.filter(record => !expired.includes(record))
        .sort((left, right) => Number(left.queued_at || 0) - Number(right.queued_at || 0) ||
          left.operation.operation_id.localeCompare(right.operation.operation_id));
      const latestByItem = new Map();
      activeRecords.forEach(record => latestByItem.set(record.operation.item_id, record));
      activeRecords.filter(record => latestByItem.get(record.operation.item_id) !== record).forEach(record => {
        storage.removeItem(record.recordKey);
        knownOperationKeys.delete(record.recordKey);
      });
      return activeRecords.filter(record => latestByItem.get(record.operation.item_id) === record)
        .map(record => ({
          ...record.operation,
          base_revision: Number.isInteger(record.operation.base_revision)
            ? record.operation.base_revision : 0,
        })).filter(operation =>
          operation && typeof operation.operation_id === 'string' &&
          ['defer', 'restore'].includes(operation.action) && typeof operation.item_id === 'string' &&
          (operation.action === 'restore' || typeof operation.wake_at === 'string'));
    } catch (_error) {
      return [];
    }
  }

  function removeOperation(operationId) {
    const storageKey = key();
    if (!storageKey || !storage) return false;
    const recordKey = storageKey + '.operation.' + encodeURIComponent(operationId);
    try {
      storage.removeItem(recordKey);
      knownOperationKeys.delete(recordKey);
      return true;
    } catch (_error) {
      return false;
    }
  }

  function operationId() {
    if (createOperationId) return createOperationId();
    if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();
    return Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);
  }

  function enqueue(action, itemId, wakeAt = null, handoff = null) {
    if (!['defer', 'restore'].includes(action) || !itemId ||
        (action === 'defer' && typeof wakeAt !== 'string') ||
        ![null, 'today'].includes(handoff)) return false;
    pending().filter(operation => operation.item_id === itemId)
      .forEach(operation => removeOperation(operation.operation_id));
    const operation = {
      operation_id: operationId(), action, item_id: itemId, wake_at: wakeAt,
      base_revision: Math.max(0, savedRevision()),
    };
    if (handoff) operation.handoff = handoff;
    const storageKey = key();
    if (!storageKey || !storage) return false;
    const recordKey = storageKey + '.operation.' + encodeURIComponent(operation.operation_id);
    let saved = false;
    try {
      storage.setItem(recordKey, JSON.stringify({ operation, queued_at: now() }));
      knownOperationKeys.add(recordKey);
      saved = true;
      coordinator?.notify('later');
    } catch (_error) { /* Report the persistence failure below. */ }
    onStatus?.(saved ? 'pending' : 'error');
    return saved;
  }

  function migrate(records) {
    const storageKey = key();
    if (!storageKey || !storage) return false;
    const marker = migrationPrefix + storageKey.slice(prefix.length);
    try {
      if (storage.getItem(marker)) return false;
      Object.entries(records || {}).forEach(([itemId, record]) => {
        const wakeAt = record && typeof record === 'object' ? record.wake_at : record;
        const handoff = record?.handoff === 'today' ? 'today' : null;
        enqueue('defer', itemId, wakeAt, handoff);
      });
      storage.setItem(marker, '1');
      return true;
    } catch (_error) {
      return false;
    }
  }

  async function run() {
    const ownerKey = key();
    if (!ownerKey) return false;
    ensureChannel();
    expiredCount = 0;
    try {
      let operations = pending();
      let plan;
      let conflictCount = 0;
      if (!operations.length) plan = await fetchJson('api/v1/later');
      while (operations.length) {
        if (key() !== ownerKey) return false;
        const batch = operations.slice(0, 50);
        plan = await fetchJson('api/v1/later', {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ operations: batch }),
        });
        const hasReceipts = Array.isArray(plan.accepted_operation_ids) ||
          Array.isArray(plan.duplicate_operation_ids) || Array.isArray(plan.rejected_operations);
        const received = hasReceipts ? [
          ...(plan.accepted_operation_ids || []),
          ...(plan.duplicate_operation_ids || []),
          ...(plan.rejected_operations || []).map(item => item.operation_id),
        ] : batch.map(item => item.operation_id);
        conflictCount += (plan.rejected_operations || [])
          .filter(item => item.reason === 'stale_intent').length;
        for (const operationId of received) {
          if (pending().some(candidate => candidate.operation_id === operationId) &&
              !removeOperation(operationId)) {
            throw new Error('Could not persist Later delivery receipt');
          }
        }
        operations = pending();
      }
      adopt(plan);
      onStatus?.(pending().length ? 'pending' :
        (conflictCount ? 'conflict' : expiredCount ? 'expired' : 'saved'),
        conflictCount ? { count: conflictCount } : expiredCount ? { count: expiredCount } : {});
      retryAttempt = 0;
      cancelRetry();
      return true;
    } catch (error) {
      if (pending().length) scheduleRetry(error, ownerKey);
      else onStatus?.('error');
      return false;
    }
  }

  function flush() {
    if (!flushing) {
      const delivery = coordinator ? coordinator.runExclusive('later', run) : run();
      flushing = Promise.resolve(delivery).finally(() => { flushing = null; });
    }
    return flushing;
  }

  function startLifecycle({ window: windowObject, document: documentObject }) {
    windowObject?.addEventListener?.('online', flush);
    documentObject?.addEventListener?.('visibilitychange', () =>
      documentObject.hidden ? false : flush()
    );
  }

  coordinator?.subscribe(change => {
    if (change.queue === 'later' && pending().length) flush();
  });

  return { enqueue, migrate, flush, pending, startLifecycle };
}

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