(() => {
  "use strict";

  if (window.top !== window || window.__stonkTikTokShopBridge) return;
  window.__stonkTikTokShopBridge = true;

  const EVENT_NAME = "STONK_TIKTOK_SHOP_PAGE_DATA";
  const INTERNAL_HOST = /(^|\.)tiktok\.com$|(^|\.)tiktokcdn(?:-us)?\.com$|(^|\.)byteoversea\.com$|(^|\.)ibytedtos\.com$|(^|\.)muscdn\.com$/i;
  const MAX_RESPONSE_SIZE = 6 * 1024 * 1024;
  const MEDIA_KEYS = new Set(["playaddr", "play_addr", "downloadaddr", "download_addr", "playurl", "play_url"]);
  const PRODUCT_ID_KEYS = ["product_id", "productid", "goods_id", "goodsid", "sku_product_id"];
  const PRODUCT_SIGNAL_KEYS = new Set([
    "product_id", "productid", "goods_id", "goodsid", "detail_url", "product_url",
    "product_name", "product_title", "sale_price", "original_price", "shop_name", "seller_name",
  ]);

  function safeUrl(value) {
    const raw = String(value || "").trim();
    if (!raw || !/^https?:\/\//i.test(raw)) return "";
    try {
      const parsed = new URL(raw, location.href);
      if (!INTERNAL_HOST.test(parsed.hostname)) return "";
      return parsed.href;
    } catch {
      return "";
    }
  }

  function firstScalar(object, keys) {
    for (const key of keys) {
      const value = object?.[key];
      if (["string", "number"].includes(typeof value) && String(value).trim()) return String(value).trim();
    }
    return "";
  }

  function firstImage(value, depth = 0) {
    if (depth > 4 || value == null) return "";
    if (typeof value === "string") return safeUrl(value);
    if (Array.isArray(value)) {
      for (const item of value.slice(0, 8)) {
        const found = firstImage(item, depth + 1);
        if (found) return found;
      }
      return "";
    }
    if (typeof value !== "object") return "";
    for (const key of ["url", "url_list", "urlList", "thumb_url_list", "uri", "image_url"]) {
      const found = firstImage(value[key], depth + 1);
      if (found) return found;
    }
    return "";
  }

  function priceText(value) {
    if (value == null) return "";
    if (["string", "number"].includes(typeof value)) return String(value).trim();
    if (typeof value !== "object") return "";
    const amount = firstScalar(value, ["amount", "sale_price", "price", "min_price", "lowest_amount"]);
    const currency = firstScalar(value, ["currency", "currency_code"]);
    return [amount, currency].filter(Boolean).join(" ");
  }

  function mediaUrls(value, depth = 0, output = []) {
    if (depth > 5 || value == null || output.length >= 8) return output;
    if (typeof value === "string") {
      const url = safeUrl(value);
      if (url && !output.includes(url)) output.push(url);
      return output;
    }
    if (Array.isArray(value)) {
      for (const item of value.slice(0, 12)) mediaUrls(item, depth + 1, output);
      return output;
    }
    if (typeof value !== "object") return output;
    for (const [key, child] of Object.entries(value)) {
      const normalized = key.replace(/[^a-z]/gi, "").toLowerCase();
      if (MEDIA_KEYS.has(normalized) || /url_?list|urllist/i.test(key)) mediaUrls(child, depth + 1, output);
    }
    return output;
  }

  function normalizeProduct(object) {
    const lowerKeys = Object.keys(object).map(key => key.toLowerCase());
    if (!lowerKeys.some(key => PRODUCT_SIGNAL_KEYS.has(key))) return null;
    const id = firstScalar(object, PRODUCT_ID_KEYS);
    if (!id || !/^\d{8,25}$/.test(id)) return null;
    const title = firstScalar(object, ["product_name", "product_title", "title", "name"]);
    const href = safeUrl(firstScalar(object, ["detail_url", "product_url", "url", "share_url"]));
    const image = firstImage(object.main_image || object.main_images || object.images || object.image || object.cover);
    const price = priceText(object.sale_price || object.price || object.price_info || object.product_price);
    const seller = firstScalar(object, ["shop_name", "seller_name", "shop_title", "merchant_name"]);
    if (!title && !href && !image && !price) return null;
    return { id, title: title || `Sản phẩm ${id}`, href, image, price, seller };
  }

  function collectPayload(root) {
    const products = new Map();
    const videos = new Map();
    const seen = new WeakSet();
    let visited = 0;

    function walk(value, depth = 0, parentVideoId = "") {
      if (value == null || depth > 12 || visited > 50000) return;
      if (typeof value !== "object") return;
      if (seen.has(value)) return;
      seen.add(value);
      visited += 1;

      if (Array.isArray(value)) {
        for (const item of value.slice(0, 1500)) walk(item, depth + 1, parentVideoId);
        return;
      }

      const videoId = firstScalar(value, ["video_id", "videoid", "item_id", "itemid", "aweme_id", "awemeid"])
        || (/^\d{15,25}$/.test(String(value.id || "")) && (value.video || value.video_data) ? String(value.id) : "")
        || parentVideoId;
      const urls = mediaUrls(value.video || value.video_data || value.videoInfo || value.video_info);
      if (videoId && urls.length) videos.set(videoId, { id: videoId, urls });

      const product = normalizeProduct(value);
      if (product) products.set(product.id, { ...(products.get(product.id) || {}), ...product, videoId: videoId || "" });

      for (const child of Object.values(value)) walk(child, depth + 1, videoId);
    }

    walk(root);
    return { products: Array.from(products.values()).slice(0, 100), videos: Array.from(videos.values()).slice(0, 30) };
  }

  function publish(value) {
    try {
      const payload = collectPayload(value);
      if (!payload.products.length && !payload.videos.length) return;
      window.postMessage({ type: EVENT_NAME, payload }, location.origin);
    } catch {
      // TikTok thay cấu trúc dữ liệu không được phép làm ảnh hưởng trang gốc.
    }
  }

  function isInternalRequest(input) {
    try {
      const raw = typeof input === "string" ? input : input?.url;
      return INTERNAL_HOST.test(new URL(raw, location.href).hostname);
    } catch {
      return false;
    }
  }

  const originalFetch = window.fetch;
  if (typeof originalFetch === "function") {
    window.fetch = function stonkTikTokShopFetch(...args) {
      const promise = originalFetch.apply(this, args);
      if (isInternalRequest(args[0])) {
        promise.then(response => {
          const type = String(response.headers.get("content-type") || "");
          const size = Number(response.headers.get("content-length") || 0);
          if (!/json|javascript|text/i.test(type) || size > MAX_RESPONSE_SIZE) return;
          response.clone().text().then(text => {
            if (!text || text.length > MAX_RESPONSE_SIZE || !/product|goods|video/i.test(text)) return;
            try { publish(JSON.parse(text)); } catch {}
          }).catch(() => {});
        }).catch(() => {});
      }
      return promise;
    };
  }

  const originalOpen = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function stonkTikTokShopOpen(method, url, ...rest) {
    this.__stonkTikTokShopUrl = isInternalRequest(url) ? String(url) : "";
    return originalOpen.call(this, method, url, ...rest);
  };
  const originalSend = XMLHttpRequest.prototype.send;
  XMLHttpRequest.prototype.send = function stonkTikTokShopSend(...args) {
    if (this.__stonkTikTokShopUrl) {
      this.addEventListener("load", () => {
        try {
          if (this.responseType && this.responseType !== "text" && this.responseType !== "json") return;
          const value = this.responseType === "json" ? this.response : JSON.parse(String(this.responseText || ""));
          publish(value);
        } catch {}
      }, { once: true });
    }
    return originalSend.apply(this, args);
  };

  function scanEmbeddedState() {
    for (const script of document.querySelectorAll('script[type="application/json"], script[id*="SIGI"], script[id*="UNIVERSAL"]')) {
      const text = String(script.textContent || "").trim();
      if (!text || text.length > MAX_RESPONSE_SIZE || !/product|goods|video/i.test(text)) continue;
      try { publish(JSON.parse(text)); } catch {}
    }
  }

  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", scanEmbeddedState, { once: true });
  else scanEmbeddedState();
  window.addEventListener("message", event => {
    if (event.source === window && event.origin === location.origin && event.data?.type === "STONK_TIKTOK_SHOP_SCAN") {
      scanEmbeddedState();
    }
  });
})();
