(function (root, factory) {
  if (typeof module === 'object' && module.exports) module.exports = factory;
  else root.createUpdateReviewHandoff = factory;
})(typeof self !== 'undefined' ? self : this, function createUpdateReviewHandoff(options) {
  let source = null;
  let completing = null;

  function eligible(detail, item = detail) {
    const merged = { ...(item || {}), ...(detail || {}) };
    return Boolean(
      merged.is_review && merged.update_reason === 'Review requested' &&
      merged.subject_type === 'Pull' && /^[^/]+\/[^/]+$/.test(String(merged.repository || '')) &&
      Number.isInteger(Number(merged.number)) && Number(merged.number) > 0 &&
      Number.isInteger(Number(merged.notification_id))
    );
  }

  function reviewItem(item) {
    return {
      ...item,
      kind: 'review',
      is_review: true,
      key: item.key || item.repository + '#' + item.number,
    };
  }

  function begin(item) {
    if (!eligible(item) || source) return false;
    source = item;
    options.openReview(reviewItem(item));
    return true;
  }

  function cancel() {
    if (!source || completing) return false;
    const item = source;
    source = null;
    options.restoreUpdate?.(item);
    return true;
  }

  function complete() {
    if (!source) return Promise.resolve(false);
    if (completing) return completing;
    const item = source;
    completing = Promise.resolve(options.admitRead(item.notification_id)).then(() => {
      options.advance(item);
      source = null;
      return true;
    }).finally(() => { completing = null; });
    return completing;
  }

  return {
    eligible,
    begin,
    cancel,
    complete,
    active: () => Boolean(source),
    source: () => source,
  };
});
