(() => {
  const main = document.getElementById("app-main");
  const footerYear = document.getElementById("footer-year");
  const pageStyleSelectors = "[data-page-style='true']";
  const pageScriptSelectors = "script[data-page-script='true']";

  const links = Array.from(document.querySelectorAll("[data-route]"));

  if (footerYear) {
    footerYear.textContent = new Date().getFullYear().toString();
  }

  function clearInjectedPageStyles() {
    document.querySelectorAll(pageStyleSelectors).forEach((node) => node.remove());
  }

  function clearInjectedPageScripts() {
    document.dispatchEvent(new CustomEvent("page:before-route-change"));
    document.querySelectorAll(pageScriptSelectors).forEach((node) => node.remove());
  }

  function injectPageStyles(parsedDocument, sourceUrl) {
    clearInjectedPageStyles();

    const head = parsedDocument.head;
    if (!head) {
      return;
    }

    const styleNodes = Array.from(head.querySelectorAll("link[rel='stylesheet'], style"));

    styleNodes.forEach((node) => {
      const clonedNode = node.cloneNode(true);
      clonedNode.setAttribute("data-page-style", "true");

      if (clonedNode.tagName === "LINK") {
        const href = clonedNode.getAttribute("href");
        if (href) {
          clonedNode.href = new URL(href, sourceUrl).toString();
        }
      }

      document.head.appendChild(clonedNode);
    });
  }

  async function injectPageScripts(parsedDocument, sourceUrl) {
    clearInjectedPageScripts();

    const scriptNodes = Array.from(parsedDocument.querySelectorAll("script"));

    for (const node of scriptNodes) {
      const scriptElement = document.createElement("script");
      scriptElement.setAttribute("data-page-script", "true");

      const src = node.getAttribute("src");
      if (src) {
        scriptElement.src = new URL(src, sourceUrl).toString();
        scriptElement.async = false;
        if (node.defer) {
          scriptElement.defer = true;
        }

        await new Promise((resolve, reject) => {
          scriptElement.onload = () => resolve();
          scriptElement.onerror = () => reject(new Error(`Impossible de charger le script: ${src}`));
          document.body.appendChild(scriptElement);
        });

        continue;
      }

      scriptElement.textContent = node.textContent;
      document.body.appendChild(scriptElement);
    }
  }

  function normalizeRoute(value) {
    const raw = (value ?? "").toString().trim().toLowerCase();
    if (!raw || raw === "/" || raw === "home" || raw === "index" || raw === "accueil") {
      return "index";
    }
    return raw.replace(/^\/+|\/+$/g, "") || "index";
  }

  function routeFromLocation() {
    const params = new URLSearchParams(window.location.search);

    if (params.has("p")) {
      return normalizeRoute(params.get("p"));
    }

    const rawSearch = window.location.search.replace(/^\?/, "");
    if (rawSearch.startsWith("p/")) {
      return normalizeRoute(rawSearch.slice(2));
    }

    if (rawSearch.startsWith("p=")) {
      return normalizeRoute(rawSearch.slice(2));
    }

    const path = window.location.pathname.replace(/^\/+|\/+$/g, "");
    if (path) {
      if (path.endsWith(".html")) {
        return "index";
      }

      const parts = path.split("/");
      if (parts[0] === "p" && parts[1]) {
        return normalizeRoute(parts.slice(1).join("/"));
      }
      return normalizeRoute(parts[0]);
    }

    return "index";
  }

  function setActiveRoute(route) {
    links.forEach((link) => {
      const isActive = link.dataset.route === route;
      if (isActive) {
        link.setAttribute("aria-current", "page");
      } else {
        link.removeAttribute("aria-current");
      }
    });
  }

  function setCanonicalUrl(route, replace = false) {
    const url = route === "index" ? "/?p/index/" : `/?p/${route}/`;
    if (replace) {
      history.replaceState({ route }, "", url);
      return;
    }
    history.pushState({ route }, "", url);
  }

  function routeToSource(route) {
    return `p/${route}/index.html`;
  }

  function routeToTitle(route) {
    if (route === "index") {
      return "Fws Web";
    }

    const label = route
      .split("/")
      .filter(Boolean)
      .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
      .join(" / ");

    return `Fws Web - ${label}`;
  }

  async function loadRoute(route) {
    clearInjectedPageScripts();

    const source = routeToSource(route);
    const response = await fetch(source, { cache: "no-store" });
    if (!response.ok) {
      throw new Error(`Impossible de charger ${source} (${response.status})`);
    }

    const html = await response.text();
    const parsed = new DOMParser().parseFromString(html, "text/html");
    injectPageStyles(parsed, response.url);
    const injected = parsed.querySelector("[data-page-content]") ?? parsed.body;
    main.innerHTML = injected.innerHTML.trim();
    await injectPageScripts(parsed, response.url);
  }

  function render(route, { replaceHistory = false } = {}) {
    const safeRoute = route || "index";

    loadRoute(safeRoute)
      .then(() => {
        setActiveRoute(safeRoute);
        setCanonicalUrl(safeRoute, replaceHistory);
        document.title = routeToTitle(safeRoute);
        window.scrollTo({ top: 0, behavior: "smooth" });
      })
      .catch((error) => {
        main.innerHTML = `<section class="hero"><h1>Erreur de chargement</h1><p class="lead">${error.message}</p></section>`;
        setActiveRoute("index");
      });
  }

  document.addEventListener("click", (event) => {
    const link = event.target.closest("[data-route]");
    if (!link) {
      return;
    }

    const route = normalizeRoute(link.dataset.route);
    if (!route) {
      return;
    }

    event.preventDefault();
    render(route);
  });

  window.addEventListener("popstate", () => {
    render(routeFromLocation(), { replaceHistory: true });
  });

  render(routeFromLocation(), { replaceHistory: true });
})();