(function(root, factory) {
  if (typeof module === 'object' && module.exports) module.exports = factory;
  else root.createMobileAppBadge = factory;
})(typeof self !== 'undefined' ? self : this, function createMobileAppBadge({
  control,
  status,
  container,
  navigator,
  storage,
  serviceWorker,
}) {
  const ENABLED_KEY = 'stackchain.app-badge.enabled.v1';
  let enabled = false;
  let confirmedCount = 0;
  let renderedCount = null;

  function available() {
    return typeof navigator?.setAppBadge === 'function'
      && typeof navigator?.clearAppBadge === 'function';
  }

  async function syncPreference() {
    try {
      const registration = await serviceWorker?.ready;
      registration?.active?.postMessage({type:'stackchain-app-badge-preference', enabled});
      return Boolean(registration?.active);
    } catch (_error) {
      return false;
    }
  }

  async function render() {
    if (!enabled || !available() || renderedCount === confirmedCount) return true;
    try {
      if (confirmedCount > 0) await navigator.setAppBadge(confirmedCount);
      else await navigator.clearAppBadge();
      renderedCount = confirmedCount;
      if (status) status.textContent = 'App icon badge is on and up to date.';
      return true;
    } catch (_error) {
      if (status) status.textContent = 'Could not update the app icon badge. Stackchain still has the confirmed count.';
      return false;
    }
  }

  async function change() {
    enabled = Boolean(control?.checked);
    if (enabled) storage?.setItem(ENABLED_KEY, 'true');
    else storage?.removeItem(ENABLED_KEY);
    await syncPreference();
    if (!enabled && available()) {
      try {
        await navigator.clearAppBadge();
        renderedCount = null;
        if (status) status.textContent = 'App icon badge is off.';
        return true;
      } catch (_error) {
        if (status) status.textContent = 'App icon badge is off, but the browser could not clear the old count.';
        return false;
      }
    }
    return render();
  }

  function start() {
    if (!available()) {
      if (container) container.hidden = true;
      if (control) control.disabled = true;
      if (status) status.textContent = 'App icon badges are unavailable in this browser.';
      return false;
    }
    enabled = storage?.getItem(ENABLED_KEY) === 'true';
    if (enabled) void syncPreference();
    if (control) {
      control.checked = enabled;
      control.addEventListener('change', change);
    }
    if (status) status.textContent = enabled ? 'App icon badge is on.' : 'App icon badge is off.';
    return true;
  }

  function readiness() {
    if (!available()) return {state:'unavailable', detail:'App icon badges are unavailable in this browser.'};
    return enabled
      ? {state:'complete', detail:'The app icon shows the confirmed unread Updates count.'}
      : {state:'incomplete', detail:'Show the confirmed unread Updates count without opening Stackchain.'};
  }

  async function enable() {
    if (!available()) return false;
    if (control) control.checked = true;
    await change();
    return true;
  }

  async function reconcile(count, {authoritative = false} = {}) {
    if (!authoritative || !Number.isSafeInteger(count) || count < 0) return false;
    confirmedCount = count;
    return render();
  }

  return {start, change, reconcile, readiness, enable};
});
