(function (root, factory) {
  if (typeof module === 'object' && module.exports) module.exports = factory;
  else {
    root.createDeviceStorage = factory;
    root.createDeviceStorage.mount = document => factory({
      summary:document.querySelector('#device-storage-summary'),
      detail:document.querySelector('#device-storage-detail'),
      clearCachesButton:document.querySelector('#clear-device-caches'),
      clearAllButton:document.querySelector('#clear-private-device-data'),
      localStorage:root.localStorage,
      sessionStorage:root.sessionStorage,
      caches:root.caches,
      storageManager:root.navigator?.storage,
      privateDatabases:root.stackchainPrivateDatabases,
      inspectPrivateDatabases:root.inspectStackchainPrivateDatabases,
      clearPrivateDeviceData:root.stackchainPrivateDeviceData,
    });
  }
})(typeof self !== 'undefined' ? self : this, function createDeviceStorage(options) {
  let privateItemCount = 0;
  let privateRecordCount = 0;
  let inventoryUnavailable = false;
  let fullClearArmed = false;
  let persistence = { state:'unavailable', detail:'Storage protection is unavailable in this browser.', label:'Unavailable' };
  const ownedCaches = async () => (await options.caches?.keys?.() || [])
    .filter(name => name.startsWith('stackchain-dashboard-'));

  function ownedStorageCount(storage) {
    if (!storage) return 0;
    let count = 0;
    for (let index = 0; index < storage.length; index += 1) {
      if (storage.key(index)?.startsWith('stackchain.')) count += 1;
    }
    return count;
  }

  function megabytes(value) {
    return Math.round((Number(value) || 0) / (1024 * 1024));
  }

  async function inspectPersistence() {
    if (typeof options.storageManager?.persisted !== 'function' || typeof options.storageManager?.persist !== 'function') {
      persistence = {state:'unavailable', detail:'Storage protection is unavailable in this browser.', label:'Unavailable'};
      return persistence;
    }
    try {
      const protectedStorage = await options.storageManager.persisted();
      persistence = protectedStorage
        ? {state:'complete', detail:'Offline work is protected from automatic browser storage cleanup.', label:'Protected'}
        : {state:'incomplete', detail:'Offline work uses best-effort browser storage and may be removed under storage pressure.', label:'Best effort'};
    } catch (_error) {
      persistence = {state:'incomplete', detail:'Storage protection could not be checked. Retry to protect offline work.', label:'Check failed'};
    }
    return persistence;
  }

  function persistenceReadiness() {
    return {state:persistence.state, detail:persistence.detail};
  }

  async function requestPersistence() {
    if (typeof options.storageManager?.persist !== 'function') return persistenceReadiness();
    let granted = false;
    try { granted = await options.storageManager.persist(); }
    catch (_error) {
      persistence = {state:'incomplete', detail:'Storage protection request failed. Offline work still uses best-effort storage; retry when ready.', label:'Request failed'};
      options.detail.textContent = options.detail.textContent.replace(/Storage protection: [^·]+/, 'Storage protection: Request failed ');
      return persistenceReadiness();
    }
    await refresh();
    if (!granted && persistence.state !== 'complete') {
      persistence = {state:'incomplete', detail:'The browser did not grant storage protection. Offline work still works but may be removed under storage pressure.', label:'Denied'};
      options.detail.textContent = options.detail.textContent.replace(/Storage protection: [^·]+/, 'Storage protection: Denied ');
    }
    return persistenceReadiness();
  }

  async function refresh() {
    let estimate = null;
    try { estimate = await options.storageManager?.estimate?.(); }
    catch (_error) { /* Storage estimates are optional. */ }
    await inspectPersistence();
    options.summary.textContent = estimate?.quota
      ? `${megabytes(estimate.usage)} MB of ${megabytes(estimate.quota)} MB browser storage used.`
      : 'Browser storage usage is unavailable.';
    const itemCount = ownedStorageCount(options.localStorage)
      + (options.sessionStorage === options.localStorage ? 0 : ownedStorageCount(options.sessionStorage));
    privateItemCount = itemCount;
    const inventory = await options.inspectPrivateDatabases?.(options.privateDatabases)
      || { recordCount: 0, unavailable: true };
    privateRecordCount = inventory.recordCount;
    inventoryUnavailable = inventory.unavailable;
    const cacheCount = (await ownedCaches()).length;
    options.detail.textContent = `Storage protection: ${persistence.label} · ${itemCount} private browser item${itemCount === 1 ? '' : 's'} · `
      + `${inventoryUnavailable ? 'private work status unknown' : `${privateRecordCount} private work record${privateRecordCount === 1 ? '' : 's'}`} · `
      + `${cacheCount} cached app cop${cacheCount === 1 ? 'y' : 'ies'}`;
    return { itemCount, privateRecordCount, inventoryUnavailable, cacheCount };
  }

  async function clearCaches() {
    options.clearCachesButton.disabled = true;
    try {
      await Promise.all((await ownedCaches()).map(name => options.caches.delete(name)));
      await refresh();
      options.summary.textContent = 'Cached app copies cleared. Private work was kept.';
    } catch (error) {
      options.summary.textContent = `Cached copies could not be cleared: ${error.message}`;
    } finally {
      options.clearCachesButton.disabled = false;
    }
  }

  async function clearAll() {
    if ((privateItemCount > 0 || privateRecordCount > 0 || inventoryUnavailable) && !fullClearArmed) {
      fullClearArmed = true;
      options.clearAllButton.textContent = 'Confirm: clear private work';
      options.summary.textContent = 'Private drafts or queued work may not be synced. Press confirm to clear them from this device.';
      return;
    }
    options.clearAllButton.disabled = true;
    try {
      await options.clearPrivateDeviceData();
      privateItemCount = 0;
      fullClearArmed = false;
      options.clearAllButton.textContent = 'Clear all private data';
      options.detail.textContent = `Storage protection: ${persistence.label} · 0 private browser items · 0 private work records · 0 cached app copies`;
      options.summary.textContent = 'All Stackchain private data was cleared from this device.';
    } catch (error) {
      options.summary.textContent = `Private data was not fully cleared: ${error.message}`;
    } finally {
      options.clearAllButton.disabled = false;
    }
  }

  async function start() {
    options.clearCachesButton.addEventListener('click', clearCaches);
    options.clearAllButton.addEventListener('click', clearAll);
    return refresh();
  }

  return { refresh, start, persistenceReadiness, requestPersistence };
});
