// OrbitCosmo URL layer — pure, dependency-free URL canonicalization.
//
// One real page can be reached by many URLs: www vs apex, http vs https port
// noise, trailing slashes, and a long tail of tracking / share params. Left
// alone these become several separate dots in the graph for the same page.
// normalizeUrl folds the safe, well-known variations into one canonical key so
// the same page is one node — WITHOUT collapsing genuinely different pages
// (e.g. ?q=A vs ?q=B on a search engine stay distinct; only known tracking
// params are dropped).
//
// Kept free of any chrome/* access so the service worker can import it
// (as an ES side-effect module), and Node tests can require() it.

(function (root) {
  "use strict";

  // Params that identify the visitor/campaign, not the page. Dropping them
  // merges share links and ad-tagged variants of the same page. Deliberately
  // conservative: nothing here changes which document a server returns.
  const TRACKING_PARAMS = [
    // Google / generic campaign tagging
    "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content",
    "utm_id", "utm_name", "utm_cid", "utm_reader",
    // Click identifiers
    "gclid", "gclsrc", "dclid", "fbclid", "yclid", "msclkid", "twclid", "ttclid",
    // Social / share
    "igshid", "igsh", "si", "ref", "ref_src", "ref_url", "referrer",
    // Email / marketing platforms
    "mc_cid", "mc_eid", "mkt_tok", "_hsenc", "_hsmi", "vero_id",
    "oly_anon_id", "oly_enc_id", "wickedid", "_branch_match_id",
    // Misc analytics
    "spm", "scid", "cmpid",
  ];

  function normalizeUrl(url) {
    try {
      const u = new URL(url);
      u.hash = "";
      // www.x.com and x.com are the same site. (URL already lowercases the host
      // and drops default ports :80/:443, so those are handled for free.)
      u.hostname = u.hostname.replace(/^www\./i, "");
      // Drop tracking / share params; keep everything else (so ?q=, ?id=,
      // ?page= — the bits that pick the actual page — survive).
      for (const p of TRACKING_PARAMS) u.searchParams.delete(p);
      // Collapse trailing slashes on a real path (/article/ == /article), but
      // keep the bare origin's "/".
      if (u.pathname !== "/") {
        u.pathname = u.pathname.replace(/\/+$/, "") || "/";
      }
      return u.toString();
    } catch {
      return url;
    }
  }

  const api = { normalizeUrl, TRACKING_PARAMS };

  if (typeof module !== "undefined" && module.exports) {
    module.exports = api;
  } else {
    Object.assign(root, api);
  }
})(typeof globalThis !== "undefined" ? globalThis : self);
