(function (root, factory) {
  if (typeof module !== 'undefined' && module.exports) {
    module.exports = options => factory({
      ...options,
      privateDatabases: require('./private-data-registry.js'),
    });
  }
  else root.stackchainPrivateDeviceData = factory({
    localStorage: root.localStorage,
    sessionStorage: root.sessionStorage,
    indexedDB: root.indexedDB,
    caches: root.caches,
    serviceWorker: root.navigator?.serviceWorker,
    MessageChannel: root.MessageChannel,
    privateDatabases: root.stackchainPrivateDatabases,
  });
})(typeof window !== 'undefined' ? window : this, function createPrivateDeviceDataPurger({
  localStorage, sessionStorage, indexedDB, caches, serviceWorker, MessageChannel, privateDatabases,
}) {
  function removeOwnedStorage(storage) {
    if (!storage) return;
    const keys = [];
    for (let index = 0; index < storage.length; index += 1) {
      const key = storage.key(index);
      if (key?.startsWith('stackchain.')) keys.push(key);
    }
    keys.forEach(key => storage.removeItem(key));
  }

  async function stopWorkerOutbox() {
    const registration = await serviceWorker?.ready;
    if (!registration?.active || !MessageChannel) return;
    await new Promise((resolve, reject) => {
      const channel = new MessageChannel();
      const timeout = setTimeout(() => reject(new Error('Background outbox purge timed out.')), 3000);
      channel.port1.onmessage = event => {
        clearTimeout(timeout);
        if (event.data?.ok) resolve();
        else reject(new Error(event.data?.error || 'Background outbox purge failed.'));
      };
      registration.active.postMessage({ type: 'stackchain-purge-outbox' }, [channel.port2]);
    });
  }

  function deletePrivateDatabase(name) {
    if (!indexedDB) return Promise.resolve();
    return new Promise((resolve, reject) => {
      let request;
      try { request = indexedDB.deleteDatabase(name); }
      catch (error) { reject(error); return; }
      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error || new Error('IndexedDB deletion failed.'));
      request.onblocked = () => reject(new Error('IndexedDB deletion was blocked.'));
    });
  }

  return async function clearPrivateDeviceData() {
    await stopWorkerOutbox();
    removeOwnedStorage(localStorage);
    if (sessionStorage !== localStorage) removeOwnedStorage(sessionStorage);
    for (const name of privateDatabases) await deletePrivateDatabase(name);
    const keys = await caches?.keys?.() || [];
    await Promise.all(
      keys.filter(key => key.startsWith('stackchain-dashboard-')).map(key => caches.delete(key))
    );
  };
});
