(function (root, factory) {
  const api = factory();
  if (typeof module !== 'undefined' && module.exports) module.exports = api;
  else root.liveDataStatus = api;
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
  const feeds = [
    ['context', 'Work'],
    ['notifications', 'Updates'],
    ['events', 'Activity'],
  ];

  function boundedSeconds(value) {
    const seconds = Number(value);
    return Number.isFinite(seconds) && seconds >= 0 ? Math.min(Math.round(seconds), 86400) : null;
  }

  function describe(freshness = {}) {
    const sections = freshness.sections || {};
    const hasSectionData = feeds.some(([key]) => Object.prototype.hasOwnProperty.call(sections, key));
    const described = feeds.map(([key, label]) => {
      const section = sections[key] || {};
      const state = section.revalidating ? 'refreshing' :
        (section.stale || section.degraded ? 'delayed' : 'live');
      return { key, label, state, ageSeconds: boundedSeconds(section.age_seconds) };
    });
    const delayed = described.filter(feed => feed.state === 'delayed');
    const refreshing = described.filter(feed => feed.state === 'refreshing');
    let summary = hasSectionData ? 'Live' : 'Live data unavailable';
    if (delayed.length === 1) summary = delayed[0].label + ' delayed';
    else if (delayed.length > 1) summary = delayed.length + ' data feeds delayed';
    else if (refreshing.length === 1) summary = refreshing[0].label + ' refreshing';
    else if (refreshing.length > 1) summary = 'Refreshing live data';
    const retryValues = described.map(feed => {
      const section = sections[feed.key] || {};
      return boundedSeconds(section.retry_in_seconds);
    }).filter(value => value !== null && value > 0);
    const aggregateRetry = boundedSeconds(freshness.retry_in_seconds);
    if (aggregateRetry !== null && aggregateRetry > 0) retryValues.push(aggregateRetry);
    return {
      summary,
      feeds: described,
      nextRetrySeconds: retryValues.length ? Math.min(...retryValues) : null,
    };
  }

  function createRefreshController({ button, output, refresh, onState = () => {} }) {
    let pending = null;
    function run() {
      if (pending) return pending;
      button.disabled = true;
      output.textContent = 'Refreshing live data…';
      onState('refreshing');
      let request;
      try {
        request = refresh();
      } catch (error) {
        request = Promise.reject(error);
      }
      pending = Promise.resolve(request).then(result => {
        if (!result) throw new Error('Live data remains unavailable.');
        output.textContent = 'Live data refreshed.';
        onState('success');
        return result;
      }).catch(error => {
        output.textContent = error && error.message ? error.message : 'Live data refresh failed.';
        onState('error');
        return null;
      }).finally(() => {
        button.disabled = false;
        pending = null;
      });
      return pending;
    }
    return { run };
  }

  function createSheetController(options) {
    let ownsDetour = false;
    let backgroundState = null;

    function focusableControls() {
      return [...options.sheet.querySelectorAll('button:not([disabled]), [tabindex]:not([tabindex="-1"])')]
        .filter(control => !control.hidden);
    }

    function containBackground() {
      if (backgroundState) return;
      backgroundState = new Map((options.backgroundElements || []).map(element => [element, element.inert]));
      backgroundState.forEach((_wasInert, element) => { element.inert = true; });
    }

    function releaseBackground() {
      if (!backgroundState) return;
      backgroundState.forEach((wasInert, element) => { element.inert = wasInert; });
      backgroundState = null;
    }

    function finishClose() {
      if (options.sheet.hidden) return;
      options.sheet.hidden = true;
      options.trigger.setAttribute('aria-expanded', 'false');
      if (options.pausedStatus) options.pausedStatus.hidden = true;
      releaseBackground();
      if (ownsDetour) options.timerView?.finishDetour?.();
      ownsDetour = false;
      options.trigger.focus?.();
    }

    function close() {
      if (options.history?.state?.liveDataStatus) {
        options.history.back();
        return;
      }
      finishClose();
    }

    function open() {
      if (!options.sheet.hidden) return;
      ownsDetour = options.timerView?.beginDetour?.('live-data-status')?.reason === 'live-data-status';
      if (options.pausedStatus) options.pausedStatus.hidden = !ownsDetour;
      if (options.returnButton) options.returnButton.hidden = !ownsDetour;
      containBackground();
      options.sheet.hidden = false;
      options.trigger.setAttribute('aria-expanded', 'true');
      if (options.history && !options.history.state?.liveDataStatus) {
        options.history.pushState({ ...options.history.state, liveDataStatus:true }, '');
      }
      options.closeButton.focus();
    }

    function start() {
      options.trigger.addEventListener('click', open);
      options.closeButton.addEventListener('click', close);
      options.returnButton?.addEventListener('click', close);
      options.sheet.addEventListener('click', event => {
        if (event.target === options.sheet) close();
      });
      options.escapeTarget?.addEventListener('keydown', event => {
        if (options.sheet.hidden) return;
        if (event.key === 'Escape') {
          event.preventDefault?.();
          close();
          return;
        }
        if (event.key !== 'Tab') return;
        const controls = focusableControls();
        if (!controls.length) return;
        const first = controls[0];
        const last = controls[controls.length - 1];
        if (event.shiftKey && event.target === first) {
          event.preventDefault();
          last.focus();
        } else if (!event.shiftKey && event.target === last) {
          event.preventDefault();
          first.focus();
        }
      });
      options.historyTarget?.addEventListener('popstate', event => {
        if (!options.sheet.hidden && !event.state?.liveDataStatus) finishClose();
      });
    }

    return { start, open, close };
  }

  function mount(options) {
    const document = options.document;
    const qs = selector => document.querySelector(selector);
    const trigger = qs('#open-live-data-status');
    trigger.addEventListener('click', options.onOpen);
    return createSheetController({
      sheet:qs('#live-data-status-sheet'), trigger,
      closeButton:qs('#close-live-data-status'),
      returnButton:qs('#return-from-live-data-status'),
      pausedStatus:qs('#live-data-status-today-paused'),
      timerView:options.timerView,
      history:options.window.history,
      historyTarget:options.window,
      escapeTarget:document,
      backgroundElements:[qs('header'), qs('main'), qs('#mobile-task-dock')].filter(Boolean),
    });
  }

  return { describe, createRefreshController, createSheetController, mount };
});
