function createNotificationUndo({ restore, onItems, onStatus, onOffer = () => {}, onClear = () => {} }) {
  let offered = null;
  let pending = false;

  return {
    offer(item, items) {
      if (!item || !Number.isInteger(item.notification_id)) return false;
      offered = { item, items: Array.isArray(items) ? [...items] : [] };
      const label = item.key || 'Update';
      onStatus(label + ' marked read. Undo?');
      onOffer(item);
      return true;
    },
    async run() {
      if (!offered || pending) return false;
      const current = offered;
      const label = current.item.key || 'Update';
      pending = true;
      onStatus('Restoring ' + label + '…');
      try {
        await restore(current.item.notification_id);
        if (offered !== current) return false;
        const restored = [current.item].concat(current.items.filter(
          item => item?.notification_id !== current.item.notification_id
        ));
        offered = null;
        onItems(restored, current.item);
        onStatus(label + ' is unread again.');
        onClear();
        return true;
      } catch (_error) {
        onStatus('Could not restore ' + label + '. Retry Undo.');
        return false;
      } finally {
        pending = false;
      }
    },
    clear() {
      offered = null;
      onClear();
    },
  };
}

async function requestNotificationUnread(notificationId) {
  const response = await fetch('api/v1/notifications/' + encodeURIComponent(notificationId) + '/unread', {
    method: 'PATCH', headers: { Accept: 'application/json' },
  });
  const payload = await response.json().catch(() => ({}));
  if (!response.ok) throw new Error(payload.error || 'Restore unread failed.');
  return payload;
}

function createDashboardNotificationUndo({ restore, getItems, setItems, getNotifications, setNotifications, refresh, select }) {
  let timer = null;
  const controller = createNotificationUndo({
    restore,
    onItems: (items, restored) => {
      setItems(items);
      const notifications = getNotifications();
      if (!notifications.some(item => item.id === restored.notification_id)) {
        setNotifications([{ id:restored.notification_id }].concat(notifications));
      }
      refresh();
    },
    onStatus: message => {
      select('#notification-undo-status').textContent = message;
      select('#my-work-action-status').textContent = message;
    },
    onOffer: item => {
      clearTimeout(timer);
      select('#notification-undo').hidden = false;
      select('#undo-notification').disabled = false;
      select('#undo-notification').setAttribute('aria-label', 'Undo marking ' + (item.key || 'update') + ' read');
      timer = setTimeout(() => controller.clear(), 10000);
    },
    onClear: () => { select('#notification-undo').hidden = true; },
  });
  return controller;
}

if (typeof module !== 'undefined' && module.exports) {
  module.exports = createNotificationUndo;
  module.exports.createDashboardNotificationUndo = createDashboardNotificationUndo;
}
