(() => {
  const pageContent = document.getElementById('page-content');
  if (!pageContent) return;

  const isModifiedEvent = (event) =>
    event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0;

  const isSameOrigin = (url) => {
    try {
      const target = new URL(url, window.location.href);
      return target.origin === window.location.origin;
    } catch {
      return false;
    }
  };

  const cloneWithAttributes = (node) => {
    const clone = document.createElement(node.tagName.toLowerCase());
    Array.from(node.attributes).forEach(attr => {
      clone.setAttribute(attr.name, attr.value);
    });
    if (node.tagName === 'SCRIPT' && node.textContent) {
      clone.textContent = node.textContent;
    }
    if (node.tagName === 'STYLE' && node.textContent) {
      clone.textContent = node.textContent;
    }
    return clone;
  };

  const replaceHeadExtras = async (doc) => {
    const oldNodes = Array.from(document.head.querySelectorAll('[data-page-head]'));
    oldNodes.forEach(node => node.remove());

    const newNodes = Array.from(doc.head.querySelectorAll('[data-page-head]'));
    const loadPromises = [];

    newNodes.forEach(node => {
      const clone = cloneWithAttributes(node);
      if (clone.tagName === 'SCRIPT' && clone.src) {
        loadPromises.push(new Promise(resolve => {
          clone.onload = resolve;
          clone.onerror = resolve;
        }));
      }
      document.head.appendChild(clone);
    });

    if (loadPromises.length) {
      await Promise.all(loadPromises);
    }
  };

  const loadPage = async (url, { push = true, scroll = true } = {}) => {
    try {
      const response = await fetch(url, {
        headers: { 'X-Requested-With': 'PageRouter' }
      });

      if (!response.ok) {
        window.location.href = url;
        return;
      }

      const html = await response.text();
      const doc = new DOMParser().parseFromString(html, 'text/html');
      const nextContent = doc.getElementById('page-content');
      if (!nextContent) {
        window.location.href = url;
        return;
      }

      const nextPageId = nextContent.dataset.pageId || '';
      const currentId = window.PageRegistry?.getCurrent?.() || pageContent.dataset.pageId || '';
      if (window.PageRegistry?.destroyCurrent) {
        await window.PageRegistry.destroyCurrent({ from: currentId, to: nextPageId, url });
      }

      document.title = doc.title;
      await replaceHeadExtras(doc);

      pageContent.innerHTML = nextContent.innerHTML;
      pageContent.dataset.pageId = nextPageId;

      if (push) {
        history.pushState({ url }, '', url);
      }

      if (scroll) {
        window.scrollTo(0, 0);
      }

      if (window.PageRegistry?.initPage) {
        await window.PageRegistry.initPage(nextPageId, { url, doc });
      }
    } catch (err) {
      window.location.href = url;
    }
  };

  document.addEventListener('click', (event) => {
    const link = event.target.closest('a[data-ajax-nav]');
    if (!link) return;
    if (isModifiedEvent(event)) return;
    if (link.target && link.target !== '_self') return;
    if (link.hasAttribute('download')) return;

    const href = link.getAttribute('href');
    if (!href || href.startsWith('#')) return;
    if (!isSameOrigin(href)) return;

    event.preventDefault();
    loadPage(href, { push: true, scroll: true });
  });

  window.addEventListener('popstate', (event) => {
    const url = (event.state && event.state.url) || window.location.href;
    loadPage(url, { push: false, scroll: false });
  });

  const boot = () => {
    const initialId = pageContent.dataset.pageId || '';
    if (window.PageRegistry?.initPage) {
      window.PageRegistry.initPage(initialId, { url: window.location.href, doc: document });
    }
  };

  window.PageRouter = { loadPage };

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', boot);
  } else {
    boot();
  }
})();
