// AdBlockMaxxer — Cookie-consent auto-dismiss (ISOLATED world, all sites).
//
// Prefers REJECT/decline over "accept all": clicks the known reject buttons of the major
// consent platforms (OneTrust, Cookiebot, Quantcast, Didomi, TrustArc, Usercentrics, Sourcepoint,
// Osano, Termly, Complianz, Borlabs…), falls back to text-matched reject buttons, then hides any
// leftover banner shell. Conservative on purpose — only well-known consent containers, never
// generic modals. Honours the "cookieDismiss" toggle, the per-site allowlist, and snooze.

(function () {
  "use strict";

  let enabled = true;
  let allowed = true;
  let snoozeUntil = 0;
  const KEY = "cookieDismiss";

  function refreshAllow(list) {
    const h = location.hostname;
    allowed = !((list || []).some((d) => h === d || h.endsWith("." + d)));
  }
  function active() { return enabled && allowed && Date.now() >= snoozeUntil; }

  chrome.storage.local.get([KEY, "allowlist", "snoozeUntil"], (r) => {
    if (r && r[KEY] === false) enabled = false;
    snoozeUntil = (r && r.snoozeUntil) || 0;
    refreshAllow(r && r.allowlist);
  });
  chrome.storage.onChanged.addListener((c) => {
    if (c[KEY]) enabled = c[KEY].newValue !== false;
    if (c.snoozeUntil) snoozeUntil = c.snoozeUntil.newValue || 0;
    if (c.allowlist) refreshAllow(c.allowlist.newValue);
  });

  // Specific reject-all buttons by consent platform.
  const REJECT_SELECTORS = [
    "#onetrust-reject-all-handler",
    ".ot-pc-refuse-all-handler",
    "#CybotCookiebotDialogBodyButtonDecline",
    "#CybotCookiebotDialogBodyLevelButtonLevelOptinDeclineAll",
    "button#didomi-notice-disagree-button",
    ".didomi-continue-without-agreeing",
    'button[onclick*="__tcfapi"]',
    ".qc-cmp2-summary-buttons button[mode='secondary']",
    "#qc-cmp2-ui button[mode='secondary']",
    "button.sp_choice_type_REJECT_ALL",
    'button[title="Reject All"]',
    ".cc-nb-reject",
    ".cmplz-deny",
    "#cookiescript_reject",
    ".cky-btn-reject",
    "#uc-btn-deny-banner",
    ".uc-deny-button",
    'button[data-testid="uc-deny-all-button"]',
    ".osano-cm-denyAll",
    "#truste-consent-required",
    ".termly-styles-reject-all",
    ".fc-cta-do-not-consent",
    'button[aria-label*="reject" i]',
    'button[aria-label*="decline" i]',
    'button[data-role="reject"]',
  ];

  // Whole-banner containers to hide if nothing got clicked.
  const BANNER_SELECTORS = [
    "#onetrust-banner-sdk",
    "#CybotCookiebotDialog",
    "#didomi-host",
    ".qc-cmp2-container",
    "#qc-cmp2-container",
    ".sp_message_container",
    "#cookiescript_injected",
    ".cky-consent-container",
    "#usercentrics-root",
    ".osano-cm-window",
    "#truste-consent-track",
    ".termly-consent-banner",
    ".cmplz-cookiebanner",
    ".cc-window",
    "#cookie-law-info-bar",
    "#cookie-notice",
  ];

  const REJECT_TEXT = /^(reject all|reject|decline all|decline|refuse all|refuse|necessary only|only necessary|deny all|deny|do not consent|continue without accepting|essential cookies only)$/i;

  let clicked = false;

  function tryClickSelectors() {
    for (const sel of REJECT_SELECTORS) {
      let btns;
      try { btns = document.querySelectorAll(sel); } catch (e) { continue; }
      for (const b of btns) {
        if (b && b.offsetParent !== null) { b.click(); return true; }
      }
    }
    return false;
  }

  function tryClickByText() {
    // Only look inside plausible consent containers to avoid nuking real "Decline" buttons.
    const scopes = BANNER_SELECTORS
      .map((s) => { try { return document.querySelector(s); } catch (e) { return null; } })
      .filter(Boolean);
    const roots = scopes.length ? scopes : [];
    for (const root of roots) {
      const btns = root.querySelectorAll("button, a[role='button'], [role='button']");
      for (const b of btns) {
        const t = (b.textContent || "").trim();
        if (t && REJECT_TEXT.test(t) && b.offsetParent !== null) { b.click(); return true; }
      }
    }
    return false;
  }

  function hideBanners() {
    let hid = false;
    for (const sel of BANNER_SELECTORS) {
      let els;
      try { els = document.querySelectorAll(sel); } catch (e) { continue; }
      for (const el of els) {
        if (el && el.style.display !== "none") { el.style.setProperty("display", "none", "important"); hid = true; }
      }
    }
    // Restore scroll the banner may have locked.
    if (hid) {
      document.documentElement.style.overflow = "";
      document.body && (document.body.style.overflow = "");
    }
    return hid;
  }

  function tick() {
    if (!active() || clicked) return;
    if (tryClickSelectors() || tryClickByText()) {
      clicked = true;
      // Some platforms reload the banner once; give it a beat, then sweep leftovers.
      setTimeout(() => { if (active()) hideBanners(); }, 600);
    }
  }

  // Banners usually inject shortly after load; poll briefly then STOP completely.
  // Most pages have no consent banner, so leaving an observer running forever would
  // burn CPU on every DOM mutation for nothing — we disconnect after the click or ~20s.
  let ticks = 0;
  let mo = null;
  function stop() {
    clearInterval(iv);
    if (mo) { mo.disconnect(); mo = null; }
  }
  const iv = setInterval(() => {
    tick();
    if (++ticks > 40 || clicked) stop(); // ~20s max, then watch nothing
  }, 500);

  // Throttle DOM-driven checks: a chatty page fires thousands of mutations; coalesce them
  // so we probe at most ~4×/sec instead of per-mutation, and tear down once handled.
  let scheduled = false;
  mo = new MutationObserver(() => {
    if (clicked || scheduled) return;
    scheduled = true;
    setTimeout(() => { scheduled = false; if (!clicked) tick(); if (clicked) stop(); }, 250);
  });
  if (document.body) mo.observe(document.body, { childList: true, subtree: true });
})();
