// AdBlockMaxxer — Floating draggable panel (ISOLATED world, all sites).
//
// Toolbar popups can't be dragged or kept open (browser limitation), so this is the
// always-on-page workaround: a small movable widget mirroring the popup's quick actions —
// live counter, snooze, zap element, pause-on-site, open settings. Toggle it with the
// Alt+Shift+A command or the popup's "Floating panel" button. Position persists per device.
//
// Built in a shadow root so the host page's CSS can never touch it.

(function () {
  "use strict";

  if (window.top !== window) return; // top frame only
  if (window.__adblockmaxxerPanel) return; // guard against on-demand re-injection
  window.__adblockmaxxerPanel = true;
  const HOST = location.hostname;

  let host = null;       // shadow host element
  let root = null;       // shadow root
  let open = false;
  let pos = null;        // {x, y}
  let snoozeUntil = 0;

  // ShadowRoot has querySelector but NOT getElementById — use this everywhere.
  const byId = (id) => (root ? root.querySelector("#" + id) : null);

  function baseDomain(h) {
    const parts = h.split(".");
    if (parts.length <= 2) return h;
    const two = ["co.uk", "com.au", "co.jp", "co.nz", "com.br"];
    return two.includes(parts.slice(-2).join(".")) ? parts.slice(-3).join(".") : parts.slice(-2).join(".");
  }

  const CSS = `
    :host { all: initial; }
    .panel {
      position: fixed; z-index: 2147483645; width: 218px;
      background: #171a21; color: #e8eaf0; border: 1px solid #2a2f3b;
      border-radius: 12px; box-shadow: 0 10px 34px rgba(0,0,0,.5);
      font: 13px/1.4 -apple-system,"Segoe UI",Roboto,sans-serif; overflow: hidden;
    }
    .hdr { display:flex; align-items:center; gap:8px; padding:9px 11px;
      background: linear-gradient(180deg,#1d212a,#171a21); cursor: move; user-select:none;
      border-bottom:1px solid #242833; }
    .hdr img { width:18px; height:18px; border-radius:5px; }
    .hdr b { font-size:12.5px; letter-spacing:.2px; flex:1; }
    .x { cursor:pointer; color:#8b91a0; font-size:15px; line-height:1; padding:2px 4px; border-radius:5px; }
    .x:hover { color:#fff; background:#242833; }
    .count { text-align:center; padding:11px 0 9px; }
    .count b { display:block; font-size:26px; font-weight:700; color:#b14cff; line-height:1; }
    .count span { color:#8b91a0; font-size:10.5px; }
    .acts { display:flex; flex-direction:column; padding:6px 10px 11px; gap:6px; }
    button.act {
      width:100%; text-align:left; padding:8px 10px; border-radius:8px; cursor:pointer;
      background:#1e222b; color:#e8eaf0; border:1px solid #2a2f3b; font-size:12.5px;
      display:flex; align-items:center; gap:8px;
    }
    button.act:hover { border-color:#b14cff; }
    button.act.on { background:rgba(177,76,255,.16); border-color:#b14cff; color:#cf9bff; }
    .ico { width:15px; text-align:center; }
  `;

  function tpl() {
    const dom = baseDomain(HOST);
    return `
      <div class="panel" part="panel">
        <div class="hdr" id="hdr">
          <img src="${chrome.runtime.getURL("icons/icon-32.png")}" alt="" />
          <b>AdBlock-Maxxer</b>
          <div class="x" id="close" title="Close (Alt+Shift+A)">✕</div>
        </div>
        <div class="count"><b id="count">0</b><span>ads skipped on this device</span></div>
        <div class="acts">
          <button class="act" id="snooze"><span class="ico">⏸</span><span id="snoozeLbl">Snooze 5 min</span></button>
          <button class="act" id="zap"><span class="ico">⌖</span>Zap an element</button>
          <button class="act" id="undo"><span class="ico">↶</span>Undo last zap</button>
          <button class="act" id="pause"><span class="ico">⦸</span><span id="pauseLbl">Pause on ${dom}</span></button>
          <button class="act" id="quest"><span class="ico">⚔</span>Daily Quest</button>
          <button class="act" id="settings"><span class="ico">⚙</span>All settings…</button>
        </div>
      </div>`;
  }

  function clampPos(p) {
    const w = 218, h = 320;
    return {
      x: Math.min(Math.max(8, p.x), Math.max(8, window.innerWidth - w - 8)),
      y: Math.min(Math.max(8, p.y), Math.max(8, window.innerHeight - h - 8)),
    };
  }

  function place() {
    const panel = root.querySelector(".panel");
    const p = clampPos(pos || { x: window.innerWidth - 234, y: 80 });
    panel.style.left = p.x + "px";
    panel.style.top = p.y + "px";
  }

  function paintCount() {
    chrome.storage.local.get("adsSkipped", (r) => {
      const el = root && byId("count");
      if (el) el.textContent = ((r && r.adsSkipped) || 0).toLocaleString();
    });
  }
  function paintSnooze() {
    const lbl = root && byId("snoozeLbl");
    const btn = root && byId("snooze");
    if (!lbl) return;
    const left = snoozeUntil - Date.now();
    if (left > 0) {
      lbl.textContent = "Resume now (" + Math.ceil(left / 60000) + "m)";
      btn.classList.add("on");
    } else {
      lbl.textContent = "Snooze 5 min";
      btn.classList.remove("on");
    }
  }
  function paintPause() {
    chrome.storage.local.get("allowlist", (r) => {
      const dom = baseDomain(HOST);
      const list = (r && r.allowlist) || [];
      const paused = list.some((d) => HOST === d || HOST.endsWith("." + d));
      const lbl = root && byId("pauseLbl");
      const btn = root && byId("pause");
      if (!lbl) return;
      lbl.textContent = (paused ? "Resume on " : "Pause on ") + dom;
      btn.classList.toggle("on", paused);
    });
  }

  // ---- drag ----------------------------------------------------------------
  function startDrag(e) {
    if (e.button !== 0) return;
    const panel = root.querySelector(".panel");
    const rect = panel.getBoundingClientRect();
    const offX = e.clientX - rect.left;
    const offY = e.clientY - rect.top;
    function move(ev) {
      pos = clampPos({ x: ev.clientX - offX, y: ev.clientY - offY });
      panel.style.left = pos.x + "px";
      panel.style.top = pos.y + "px";
    }
    function up() {
      document.removeEventListener("mousemove", move, true);
      document.removeEventListener("mouseup", up, true);
      if (pos) chrome.storage.local.set({ panelPos: pos });
    }
    document.addEventListener("mousemove", move, true);
    document.addEventListener("mouseup", up, true);
    e.preventDefault();
  }

  // ---- build / teardown ----------------------------------------------------
  function build() {
    if (host) return;
    host = document.createElement("div");
    host.id = "adblockmaxxer-panel-host";
    root = host.attachShadow ? host.attachShadow({ mode: "open" }) : host;
    const style = document.createElement("style");
    style.textContent = CSS;
    const wrap = document.createElement("div");
    wrap.innerHTML = tpl();
    root.appendChild(style);
    root.appendChild(wrap.firstElementChild);
    document.documentElement.appendChild(host);

    byId("hdr").addEventListener("mousedown", startDrag);
    byId("close").addEventListener("click", () => setOpen(false));
    byId("snooze").addEventListener("click", () => {
      if (snoozeUntil - Date.now() > 0) chrome.runtime.sendMessage({ type: "unsnooze" });
      else chrome.runtime.sendMessage({ type: "snooze", minutes: 5 });
    });
    byId("zap").addEventListener("click", () => {
      window.dispatchEvent(new Event("abm-zap-start"));
      setOpen(false); // get out of the way so you can click the target
    });
    byId("undo").addEventListener("click", () => window.dispatchEvent(new Event("abm-zap-undo")));
    byId("pause").addEventListener("click", () => {
      const dom = baseDomain(HOST);
      chrome.storage.local.get("allowlist", (r) => {
        let list = (r && r.allowlist) || [];
        if (list.includes(dom)) list = list.filter((d) => d !== dom);
        else list.push(dom);
        chrome.storage.local.set({ allowlist: list });
      });
    });
    byId("quest").addEventListener("click", () => chrome.storage.local.set({ sysOpen: true }));
    byId("settings").addEventListener("click", () => chrome.runtime.sendMessage({ type: "openOptions" }));

    place();
    paintCount();
    paintSnooze();
    paintPause();
  }

  function teardown() {
    if (host && host.parentNode) host.parentNode.removeChild(host);
    host = null; root = null;
  }

  function setOpen(v) {
    open = v;
    chrome.storage.local.set({ panelOpen: v });
    if (v) build(); else teardown();
  }

  // ---- wiring --------------------------------------------------------------
  chrome.storage.local.get(["panelOpen", "panelPos", "snoozeUntil"], (r) => {
    pos = (r && r.panelPos) || null;
    snoozeUntil = (r && r.snoozeUntil) || 0;
    if (r && r.panelOpen) setOpen(true);
  });
  chrome.storage.onChanged.addListener((c) => {
    if (c.adsSkipped && root) paintCount();
    if (c.snoozeUntil) { snoozeUntil = c.snoozeUntil.newValue || 0; if (root) paintSnooze(); }
    if (c.allowlist && root) paintPause();
    // honour open/close made from another surface (popup button, another tab)
    if (c.panelOpen && !!c.panelOpen.newValue !== open) {
      open = !!c.panelOpen.newValue;
      if (open) build(); else teardown();
    }
  });
  chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
    if (msg && msg.type === "cmd" && msg.cmd === "toggle-panel") {
      setOpen(!open);
      // Reply so the sender's callback doesn't get a spurious "message port closed"
      // lastError — that was making the popup re-inject + double-toggle (panel flashed shut).
      try { sendResponse({ ok: true }); } catch (e) {}
    }
  });

  // keep the snooze countdown fresh while open
  setInterval(() => { if (root) paintSnooze(); }, 30000);
  window.addEventListener("resize", () => { if (root) place(); });
})();
