(() => {
  "use strict";
  const bridge = window.chrome && window.chrome.webview ? window.chrome.webview : null;

  let snapshot = null;          // { Sources, Items, Errors, UpdatedAt } from news.get
  let loading = false;
  let drawerOpen = false;
  let pendingToggle = null;     // 2-step remove confirm per row (feed -> timer)
  let loadTimer = null;         // debounce for post-save reloads (declared early —
                                // load() below runs before the old declaration site)
  let sourceFilter = null;      // Feed URL when a sidebar source is selected (null = all)

  // ---- Monochrome icons (stroke figures, currentColor) ----
  const FIG = {
    refresh: "M 3 12 A 9 9 0 1 0 12 3 A 9.75 9.75 0 0 0 5.26 5.74 L 3 8 M 3 3 L 3 8 L 8 8",
    x: "M 18 6 L 6 18 M 6 6 l 12 12",
    news: "M 4 22 h 16 a 2 2 0 0 0 2 -2 V 4 a 2 2 0 0 0 -2 -2 H 8 a 2 2 0 0 0 -2 2 v 16 a 2 2 0 0 1 -4 0 V 9 M 18 14 h -8 M 15 18 h -5 M 10 6 h 8 v 4 h -8 z",
  };
  function icoSVG(fig, size) {
    const s = size || 16;
    return '<svg viewBox="0 0 24 24" width="' + s + '" height="' + s + '" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="' + fig + '"/></svg>';
  }
  document.getElementById("refreshBtn").innerHTML = icoSVG(FIG.refresh, 17);
  document.getElementById("closeDrawer").innerHTML = icoSVG(FIG.x, 16);

  // ---------- bridge ----------
  function post(m) { if (bridge) bridge.postMessage(m); }
  function ask(t, extra) { const m = { type: t }; if (extra) Object.assign(m, extra); post(m); }

  window.addEventListener("error", (e) => post({ type: "log", msg: "news JS error: " + (e.message || "") + " @" + (e.lineno || "") + ":" + (e.colno || "") }));
  window.addEventListener("unhandledrejection", (e) => post({ type: "log", msg: "news unhandled: " + ((e.reason && e.reason.message) || e.reason) }));

  const $ = (id) => document.getElementById(id);
  const esc = (s) => String(s == null ? "" : s).replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));

  function onHostMessage(e) {
    let msg;
    try { msg = typeof e.data === "string" ? JSON.parse(e.data) : e.data; } catch { return; }
    if (!msg || !msg.type) return;
    if (msg.type === "theme") { setTheme(msg.theme, msg.accent); }
    else if (msg.type === "news.data") { snapshot = msg.data || null; renderAll(); }
    else if (msg.type === "news.saved") { scheduleLoad(); }
    else if (msg.type === "news.added") { handleAdded(msg); }
  }
  if (bridge) bridge.addEventListener("message", onHostMessage);
  window.addEventListener("message", onHostMessage);

  ask("browser.theme");
  load(false);

  // ---------- theme (mirrors settings/apps pages: accent-hued dark) ----------
  function hexToRgb(hex) {
    let h = String(hex || "").replace("#", "");
    if (h.length === 3) h = h.split("").map((c) => c + c).join("");
    const n = parseInt(h, 16);
    if (isNaN(n)) return { r: 4, g: 180, b: 48 };
    return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
  }
  function setTheme(theme, accent) {
    const t = theme === "System" ? "auto" : (theme || "auto");
    const dark = t === "dark" || (t === "auto" && window.matchMedia("(prefers-color-scheme: dark)").matches);
    document.documentElement.dataset.theme = dark ? "dark" : "light";
    try { localStorage.setItem("pako-news-theme", dark ? "dark" : "light"); } catch (_) {}
    if (accent) document.documentElement.style.setProperty("--accent", accent);
    const c = hexToRgb(accent || "#04B430");
    const d = document.documentElement;
    if (dark) {
      d.style.setProperty("--bg", "rgb(" + Math.round(c.r * 0.05) + "," + Math.round(c.g * 0.05) + "," + Math.round(c.b * 0.05) + ")");
      d.style.setProperty("--panel", "rgb(" + Math.round(c.r * 0.10) + "," + Math.round(c.g * 0.10) + "," + Math.round(c.b * 0.10) + ")");
      d.style.setProperty("--border", "rgba(" + c.r + "," + c.g + "," + c.b + ",0.18)");
    } else {
      d.style.removeProperty("--bg"); d.style.removeProperty("--panel"); d.style.removeProperty("--border");
    }
  }

  // ---------- language filter ----------
  let lang = "all";
  try { const s = localStorage.getItem("pako-news-lang"); if (s === "all" || s === "ne" || s === "en") lang = s; } catch (_) {}
  const langBtns = document.querySelectorAll("#langPills .pill");
  langBtns.forEach((b) => {
    b.classList.toggle("on", b.dataset.lang === lang);
    b.addEventListener("click", () => {
      lang = b.dataset.lang;
      try { localStorage.setItem("pako-news-lang", lang); } catch (_) {}
      langBtns.forEach((x) => x.classList.toggle("on", x === b));
      renderFeed();
    });
  });

  // ---------- load / refresh ----------
  function scheduleLoad() {
    if (loadTimer) clearTimeout(loadTimer);
    loadTimer = setTimeout(() => load(true), 320);
  }
  function load(force) {
    if (loadTimer) { clearTimeout(loadTimer); loadTimer = null; }
    loading = true;
    $("refreshBtn").classList.add("spin");
    $("statusTxt").textContent = "Refreshing the latest stories…";
    ask("news.get", force ? { refresh: true } : undefined);
  }
  $("refreshBtn").addEventListener("click", () => { if (!loading) load(true); });
  $("emptyRefresh").addEventListener("click", () => load(true));

  // ---------- helpers ----------
  function hostOf(url) {
    try { return new URL(url).host; } catch { return ""; }
  }
  function favicon(url) {
    const h = hostOf(url);
    if (!h) return "";
    return "https://www.google.com/s2/favicons?domain=" + encodeURIComponent(h) + "&sz=64";
  }
  function initial(name) {
    const n = (name || "?").trim();
    return n ? n.charAt(0).toUpperCase() : "?";
  }

  function mediaHtml(img, init, cls) {
    if (img) {
      return '<div class="' + cls + '"><span class="ph">' + esc(init) + "</span><img loading=\"lazy\" src=\"" + esc(img) + '" referrerpolicy="no-referrer" onerror="this.style.display=\'none\'" alt=""></div>';
    }
    return '<div class="' + cls + '"><span class="ph">' + esc(init) + "</span></div>";
  }

  const NP_DIGITS = { 0: "०", 1: "१", 2: "२", 3: "३", 4: "४", 5: "५", 6: "६", 7: "७", 8: "८", 9: "९" };
  function npNum(n) { return String(n).replace(/\d/g, (d) => NP_DIGITS[d]); }

  function relTime(iso, itemLang) {
    if (!iso) return "";
    const d = new Date(iso);
    if (isNaN(d.getTime())) return "";
    const sec = Math.floor((Date.now() - d.getTime()) / 1000);
    const np = itemLang === "ne";
    if (sec < 60) return np ? "अहिले" : "just now";
    const min = Math.floor(sec / 60);
    if (min < 60) return np ? npNum(min) + " मिनेट अघि" : min + "m ago";
    const hr = Math.floor(min / 60);
    if (hr < 24) return np ? npNum(hr) + " घण्टा अघि" : hr + "h ago";
    const dy = Math.floor(hr / 24);
    if (dy < 7) return np ? npNum(dy) + " दिन अघि" : dy + "d ago";
    return np ? npNum(d.getDate()) + " " + d.toLocaleDateString("en-GB", { month: "short", year: "numeric" }).split(" ").slice(1).join(" ") : d.toLocaleDateString("en-GB", { day: "numeric", month: "short" });
  }

  function sourceMeta(item) {
    const f = favicon(item.Feed);
    return (f ? '<img src="' + esc(f) + '" referrerpolicy="no-referrer" alt="" onerror="this.remove()">' : "") +
      '<span class="src">' + esc(item.Source) + "</span>" +
      '<span class="dt">· ' + esc(relTime(item.Date, item.Lang)) + "</span>";
  }

  function filteredItems() {
    if (!snapshot) return [];
    return snapshot.Items.filter((i) =>
      (lang === "all" || i.Lang === lang) &&
      (!sourceFilter || i.Feed === sourceFilter));
  }

  // ---------- source sidebar (Facebook-style left rail) ----------
  function renderSourcesSide() {
    const list = $("sideList");
    if (!snapshot) return;
    const srcs = snapshot.Sources || [];
    const counts = {};
    (snapshot.Items || []).forEach((i) => { counts[i.Feed] = (counts[i.Feed] || 0) + 1; });

    let html = srcRowHtml(null, "All sources", counts);
    srcs.filter((s) => s.Enabled).forEach((s) => {
      html += srcRowHtml(s.Feed, s.Name, counts);
    });
    list.innerHTML = html;
  }

  function srcRowHtml(feed, name, counts) {
    const on = (sourceFilter && feed && sourceFilter === feed) || (!sourceFilter && !feed);
    const f = feed ? favicon(feed) : "";
    const cnt = feed ? (counts[feed] || 0) : (snapshot ? snapshot.Items.length : 0);
    const ico = f
      ? '<img src="' + esc(f) + '" referrerpolicy="no-referrer" alt="" onerror="this.remove()">'
      : '<span class="ic">' + esc(initial(name)) + "</span>";
    return '<button type="button" class="src-it' + (on ? " on" : "") + '" data-feed="' + esc(feed || "") + '" title="' + esc(name) + '">' +
      ico + '<span class="nm">' + esc(name) + "</span><span class=\"ct\">" + cnt + "</span></button>";
  }

  $("sideList").addEventListener("click", (e) => {
    const btn = e.target.closest(".src-it");
    if (!btn) return;
    sourceFilter = btn.dataset.feed || null;
    renderAll();
  });

  // ---------- render ----------
  function renderAll() {
    renderStatus();
    renderSourcesSide();
    renderFeed();
    if (drawerOpen) renderSources();
  }

  function renderStatus() {
    const snap = snapshot;
    if (!snap) return;
    const off = (snap.Errors || []).length;
    const bar = $("statusBar");
    const txt = $("statusTxt");
    loading = false;
    $("refreshBtn").classList.remove("spin");
    if (!snap.Items || !snap.Items.length) {
      bar.classList.add("err");
      txt.textContent = off ? "Couldn't load any feeds right now — check your connection." : "No stories yet.";
      return;
    }
    bar.classList.toggle("err", off > 0);
    txt.textContent = off
      ? off + " source" + (off > 1 ? "s" : "") + " unavailable — showing the rest"
      : "Updated " + relTime(snap.UpdatedAt, "en").replace(" ago", "") + " ago";
  }

  function renderFeed() {
    const heroBox = $("heroBox");
    const grid = $("grid");
    const empty = $("emptyBox");
    const items = filteredItems();
    $("storyCount").textContent = snapshot ? items.length : 0;

    if (!items.length) {
      heroBox.innerHTML = "";
      grid.innerHTML = "";
      $("emptyMsg").textContent = snapshot && (snapshot.Errors || []).length
        ? "None of your sources could be reached right now. Check your internet connection and try again."
        : sourceFilter ? "No stories from this source right now — pick another from the list."
        : lang === "all" ? "Turn on a source below or refresh to fetch the latest headlines." : "No stories in this language right now — try another tab or add a source.";
      empty.style.display = "";
      return;
    }
    empty.style.display = "none";

    // Hero = the freshest story that has an image (falls back to the top story).
    let heroIdx = 0;
    for (let i = 0; i < items.length; i++) {
      if (items[i].Image) { heroIdx = i; break; }
    }
    const hero = items[heroIdx];

    const hFav = favicon(hero.Feed);
    heroBox.innerHTML = '<a class="n-hero" href="' + esc(hero.Link) + '" target="_blank" rel="noopener">' +
      mediaHtml(hero.Image, initial(hero.Source), "h-img") +
      '<div class="h-body"><div class="n-kicker">' +
      (hFav ? '<img src="' + esc(hFav) + '" alt="" onerror="this.remove()" referrerpolicy="no-referrer">' : "") +
      "<span>" + esc(hero.Source) + "</span><span class=\"sep\">·</span><span class=\"t\">" + esc(relTime(hero.Date, hero.Lang)) + "</span></div>" +
      "<h2>" + esc(hero.Title) + "</h2>" +
      (hero.Excerpt ? "<p>" + esc(hero.Excerpt) + "</p>" : "") + "</div></a>";

    const rest = items.filter((_, i) => i !== heroIdx);
    grid.innerHTML = rest.map((it) =>
      '<a class="nc" href="' + esc(it.Link) + '" target="_blank" rel="noopener">' +
      mediaHtml(it.Image, initial(it.Source), "nc-img") +
      '<div class="nc-body"><div class="nc-title">' + esc(it.Title) + "</div>" +
      (it.Excerpt ? '<div class="nc-ex">' + esc(it.Excerpt) + "</div>" : "") +
      '<div class="nc-foot">' + sourceMeta(it) + "</div></div></a>"
    ).join("");
  }

  // ---------- toast ----------
  let toastTimer = null;
  function toast(msg) {
    const t = $("toast");
    t.textContent = msg;
    t.classList.add("show");
    if (toastTimer) clearTimeout(toastTimer);
    toastTimer = setTimeout(() => t.classList.remove("show"), 2600);
  }

  // ---------- sources drawer ----------
  function openDrawer() {
    drawerOpen = true;
    $("ovl").classList.add("show");
    $("drawer").classList.add("show");
    renderSources();
    setTimeout(() => $("addUrl").focus(), 260);
  }
  function closeDrawer() {
    drawerOpen = false;
    $("ovl").classList.remove("show");
    $("drawer").classList.remove("show");
    $("addMsg").textContent = "";
    $("addMsg").className = "dr-msg";
  }
  $("sourcesBtn").addEventListener("click", openDrawer);
  $("closeDrawer").addEventListener("click", closeDrawer);
  $("ovl").addEventListener("click", closeDrawer);
  document.addEventListener("keydown", (e) => {
    if (e.key === "Escape" && drawerOpen) closeDrawer();
  });

  function renderSources() {
    const list = $("srcList");
    const srcs = snapshot ? snapshot.Sources : [];
    const active = srcs.filter((s) => s.Enabled).length;
    $("srcCount").textContent = srcs.length + " sources · " + active + " active";
    if (!srcs.length) { list.innerHTML = '<div class="dr-hint">Loading your sources…</div>'; return; }

    list.innerHTML = "";
    srcs.forEach((s) => {
      const row = document.createElement("div");
      row.className = "src-row" + (s.Enabled ? "" : " off");

      const favWrap = document.createElement("div");
      favWrap.className = "fav";
      const f = favicon(s.Feed);
      if (f) {
        const img = document.createElement("img");
        img.src = f;
        img.referrerPolicy = "no-referrer";
        img.alt = "";
        img.onerror = () => { img.remove(); };
        favWrap.appendChild(img);
      }
      const ini = document.createElement("span");
      ini.className = "init";
      ini.textContent = initial(s.Name);
      favWrap.appendChild(ini);
      // If a favicon loaded, hide the initial underneath it.
      row.appendChild(favWrap);

      const meta = document.createElement("div");
      meta.className = "meta";
      meta.innerHTML = '<div class="nm">' + esc(s.Name) + "</div>" +
        '<span class="lg">' + (s.Lang === "ne" ? "नेपाली" : "EN") + "</span>";
      row.appendChild(meta);

      if (s.Custom) {
        const rm = document.createElement("button");
        rm.className = "rm";
        rm.title = "Remove source";
        rm.innerHTML = icoSVG(FIG.x, 14);
        rm.addEventListener("click", () => {
          if (pendingToggle && pendingToggle.row === row) {
            clearTimeout(pendingToggle.t);
            pendingToggle = null;
            ask("news.remove", { feed: s.Feed });
            scheduleLoad();
            toast("Removed " + s.Name);
          } else {
            if (pendingToggle) { clearTimeout(pendingToggle.t); pendingToggle.row.querySelector(".rm").innerHTML = icoSVG(FIG.x, 14); }
            rm.innerHTML = "Remove";
            rm.style.fontSize = "11px";
            rm.style.padding = "0 4px";
            pendingToggle = {
              row: row,
              t: setTimeout(() => {
                rm.innerHTML = icoSVG(FIG.x, 14);
                rm.style.fontSize = "";
                rm.style.padding = "";
                if (pendingToggle && pendingToggle.row === row) pendingToggle = null;
              }, 4000),
            };
          }
        });
        row.appendChild(rm);
      }

      const tg = document.createElement("button");
      tg.className = "toggle" + (s.Enabled ? " on" : "");
      tg.title = s.Enabled ? "Disable this source" : "Enable this source";
      tg.addEventListener("click", () => {
        tg.disabled = true;
        ask("news.setEnabled", { feed: s.Feed, on: !s.Enabled });
        scheduleLoad();
      });
      row.appendChild(tg);

      list.appendChild(row);
    });
  }

  // ---------- add source ----------
  let addLang = "auto"; // auto | en | ne — picked on the add-source form
  const addLangBtns = document.querySelectorAll("#addLangPills .pill");
  addLangBtns.forEach((b) => b.addEventListener("click", () => {
    addLang = b.dataset.lang;
    addLangBtns.forEach((x) => x.classList.toggle("on", x === b));
  }));

  function handleAdded(msg) {
    const out = $("addMsg");
    out.className = "dr-msg " + (msg.ok ? "ok" : "err");
    if (msg.ok) {
      out.textContent = "Added " + msg.name + " — fetching its latest stories…";
      $("addUrl").value = "";
      // Reset the language picker back to Auto for the next add.
      addLang = "auto";
      addLangBtns.forEach((x) => x.classList.toggle("on", x.dataset.lang === "auto"));
      scheduleLoad();
    } else {
      out.textContent = msg.error || "Couldn't add that source.";
      $("addBtn").disabled = false;
    }
  }
  $("addBtn").addEventListener("click", () => {
    const url = $("addUrl").value.trim();
    if (!url) { $("addMsg").className = "dr-msg err"; $("addMsg").textContent = "Enter a feed URL first."; return; }
    $("addBtn").disabled = true;
    $("addMsg").className = "dr-msg";
    $("addMsg").textContent = "Checking the feed…";
    const lang = addLang === "auto" ? "" : addLang;
    ask("news.add", { url, lang });
  });
  $("addUrl").addEventListener("keydown", (e) => { if (e.key === "Enter") $("addBtn").click(); });
})();
