console.log("Common content script loaded");

// (function markBlackEagleInstalled() {
//   try {
//     if (document?.documentElement) {
//       document.documentElement.setAttribute("data-blackeagle-installed", "true");
//     }
//     if (typeof window !== "undefined") {
//       window.dispatchEvent(new CustomEvent("blackeagle:installed"));
//     }
//   } catch (e) {
//     // no-op
//   }
// })();

var videoInfo = null;
let lastUrl = location.href;
let pendingMutationRefresh = null;

function scheduleContentRefresh() {
  // Debounce to avoid spamming refresh during large DOM updates.
  if (pendingMutationRefresh) {
    clearTimeout(pendingMutationRefresh);
  }
  pendingMutationRefresh = setTimeout(() => {
    pendingMutationRefresh = null;
    void changeWeb();
  }, 600);
}

function handleUrlChange() {
  // Avoid redundant refreshes if URL did not actually change
  if (location.href === lastUrl) return;
  lastUrl = location.href;
  void changeWeb();
}

// Patch History API to detect SPA navigations (e.g., Reddit/Twitter)
const _pushState = history.pushState;
history.pushState = function pushStatePatched(...args) {
  const ret = _pushState.apply(this, args);
  handleUrlChange();
  return ret;
};

const _replaceState = history.replaceState;
history.replaceState = function replaceStatePatched(...args) {
  const ret = _replaceState.apply(this, args);
  handleUrlChange();
  return ret;
};

// Observe DOM changes to catch SPA content swaps where URL does not change.
const mutationObserver = new MutationObserver(() => {
  scheduleContentRefresh();
});
mutationObserver.observe(document.documentElement || document.body, {
  childList: true,
  subtree: true,
  characterData: true,
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "READ_WEB") {
    (async () => {
      const webcontent = {
        url: location.href,
        title: document.title || "",
        videoInfo: videoInfo,
        imageInfo: [],
        description: document.querySelector('meta[name="description"]')?.content || "",
        keywords: document.querySelector('meta[name="keywords"]')?.content || "",
        content: document.body.innerText || document.body.textContent,
        contentHTML: document.body.innerHTML || "",
      };

      await buildVideoInfo(webcontent);
      await buildImageInfo(webcontent);

      sendResponse({
        success: true,
        webcontent,
      });
    })();

    return true;
  }
});

async function buildVideoInfo(webcontent) {
  if (webcontent.videoInfo == null) {
    try {
      const currentUrl = location.href;
      const apiUrl = `https://api.mir6.com/api/bzjiexi?url=${encodeURIComponent(currentUrl)}&type=json`;
      const response = await fetch(apiUrl);
      // 检查状态
      if (response.ok) {
        const data = await response.json();
        if (data.code == 200) {
          videoInfo = data;
          webcontent.videoInfo = data.data;
        } else {
          videoInfo = "";
        }
      }
    } catch (err) {}
  }
}

async function buildImageInfo(webcontent) {
  const seen = new Set();
  const images = Array.from(document.querySelectorAll("img")).map((img) => {
    const rawSrc = img.getAttribute("src") || img.currentSrc || img.dataset?.src || "";
    let src = rawSrc;
    try {
      src = new URL(rawSrc, location.href).href;
    } catch (e) {}

    const description = (img.getAttribute("alt") || img.getAttribute("title") || img.getAttribute("aria-label") || "").trim();
    return { src, description };
  });

  webcontent.imageInfo = images.filter((img) => {
    if (!img.src) return false;
    if (seen.has(img.src)) return false;
    seen.add(img.src);
    return true;
  });
}

async function changeWeb() {
  // Keep lastUrl in sync for manual refresh triggers
  lastUrl = location.href;
  const webcontent = {
    url: location.href,
    title: document.title || "",
    imageInfo: [],
    description: document.querySelector('meta[name="description"]')?.content || "",
    keywords: document.querySelector('meta[name="keywords"]')?.content || "",
    content: document.body.innerText || document.body.textContent,
    contentHTML: document.body.innerHTML || "",
  };
  await buildVideoInfo(webcontent);
  await buildImageInfo(webcontent);
  chrome.runtime.sendMessage({ type: "CHECK_ACTIVE_TAB" }, (res) => {
    const err = chrome.runtime.lastError;
    if (err || !res) return;

    if (res.isActive) {
      try {
        chrome.runtime.sendMessage({ type: "CHANGE_WEB", webcontent: webcontent }, (response) => {
          const sendErr = chrome.runtime.lastError;
          if (sendErr) {
            console.warn("sendMessage failed:", sendErr);
          }
        });
      } catch (e) {
        console.warn("sendMessage error:", e);
      }
    }
  });
}

function pageSelectedText() {
  const text = window.getSelection().toString();
  chrome.runtime.sendMessage({ type: "SELECTED_TEXT", text: text }, () => {
    // Touch lastError to silence "Receiving end does not exist" when background is inactive.
    void chrome.runtime.lastError;
  });
}

document.addEventListener("mouseup", () => pageSelectedText());
window.addEventListener("visibilitychange", async () => await changeWeb());
document.addEventListener("DOMContentLoaded", async () => await changeWeb());

// Handle browser history navigation and SPA route changes
window.addEventListener("popstate", () => {
  // Back/forward via History API
  handleUrlChange();
});
window.addEventListener("hashchange", () => {
  // URL hash changes (common in SPAs)
  handleUrlChange();
});
window.addEventListener("pageshow", (e) => {
  // BFCache restore or normal show; ensure webcontent stays in sync
  // If desired, you can gate on e.persisted, but updating is inexpensive.
  handleUrlChange();
});

window.addEventListener("error", (e) => {
  if (e.message?.includes("Extension context invalidated")) {
    e.preventDefault();
  }
});

window.addEventListener("unhandledrejection", (e) => {
  if (e.reason?.message?.includes("Extension context invalidated")) {
    e.preventDefault();
  }
});

setTimeout(() => changeWeb(), 1000);
