/**
 * 熊猫ERP 1688 单商品事实采集器。
 * 只回传页面中真实存在的字段，不生成关键词、卖点或缺失规格。
 */
(function() {
  'use strict';

  if (!/\.1688\.com$/i.test(location.hostname) || !/\/offer\/\d+/i.test(location.pathname)) return;

  var COLLECTOR_VERSION = '5.2.66';
  var MAX_SCRIPT_SIZE = 2500000;
  var FAST_SCRIPT_SIZE = 420000;
  var PANDA_APP_HOST = 'https://sczfai.com';
  var PRELOAD_MAX_AGE = 90 * 1000;

  function clean(value, limit) {
    var text = String(value == null ? '' : value).replace(/\u00a0/g, ' ').replace(/\s+/g, ' ').trim();
    return limit ? text.slice(0, limit) : text;
  }

  function absoluteUrl(value) {
    var url = clean(value, 2000);
    if (!url || url.indexOf('data:') === 0 || url.indexOf('blob:') === 0) return '';
    if (url.indexOf('//') === 0) url = 'https:' + url;
    try { return new URL(url, location.href).href; } catch (error) { return ''; }
  }

  function mediaUrl(value) {
    var url = absoluteUrl(value);
    if (!url || /sprite|icon|logo|avatar|placeholder|loading/i.test(url)) return '';
    return url.split('?')[0];
  }

  function imageValue(value) {
    if (typeof value === 'string') {
      if (/^img\/ibank\//i.test(value)) return 'https://cbu01.alicdn.com/' + value;
      return value;
    }
    if (!value || typeof value !== 'object') return '';
    return value.fullPathImageURI || value.fullPathImageUrl || value.imageURI || value.imageUrl
      || value.picUrl || value.url || value.src || value.summImageURI || value.searchImageURI || '';
  }

  function pushUnique(list, value) {
    var url = mediaUrl(value);
    if (url && list.indexOf(url) === -1) list.push(url);
  }

  function numberOrNull(value) {
    if (value === undefined || value === null || value === '') return null;
    var match = String(value).replace(',', '.').match(/-?\d+(?:\.\d+)?/);
    if (!match) return null;
    var number = parseFloat(match[0]);
    return Number.isFinite(number) ? number : null;
  }

  function offerId() {
    var match = location.pathname.match(/\/offer\/(\d+)/i);
    return match ? match[1] : '';
  }

  function draftId() {
    try { return new URL(location.href).searchParams.get('qydz_draft_id') || ''; } catch (error) { return ''; }
  }

  function extractBalanced(text, start) {
    var first = text[start];
    if (first !== '{' && first !== '[') return '';
    var open = first;
    var close = first === '{' ? '}' : ']';
    var depth = 0;
    var quote = '';
    var escaped = false;
    for (var i = start; i < text.length; i += 1) {
      var char = text[i];
      if (quote) {
        if (escaped) escaped = false;
        else if (char === '\\') escaped = true;
        else if (char === quote) quote = '';
        continue;
      }
      if (char === '"' || char === "'") { quote = char; continue; }
      if (char === open) depth += 1;
      if (char === close) {
        depth -= 1;
        if (depth === 0) return text.slice(start, i + 1);
      }
    }
    return '';
  }

  function valueAfterKey(text, key) {
    var needles = ['"' + key + '"', "'" + key + "'", key];
    for (var n = 0; n < needles.length; n += 1) {
      var index = text.indexOf(needles[n]);
      while (index >= 0) {
        var colon = text.indexOf(':', index + needles[n].length);
        if (colon < 0 || colon - index > 80) break;
        var start = colon + 1;
        while (/\s/.test(text[start] || '')) start += 1;
        var json = extractBalanced(text, start);
        if (json) {
          try { return JSON.parse(json); } catch (error) {}
        }
        index = text.indexOf(needles[n], index + needles[n].length);
      }
    }
    return null;
  }

  function assignedJson(text, names) {
    for (var i = 0; i < names.length; i += 1) {
      var index = text.indexOf(names[i]);
      if (index < 0) continue;
      var equals = text.indexOf('=', index + names[i].length);
      if (equals < 0 || equals - index > 80) continue;
      var start = equals + 1;
      while (/\s/.test(text[start] || '')) start += 1;
      var json = extractBalanced(text, start);
      if (json) {
        try { return JSON.parse(json); } catch (error) {}
      }
    }
    return null;
  }

  function collectEmbeddedData(options) {
    options = options || {};
    var selected = {};
    var jsonLd = [];
    var stateRoots = [];
    var keys = ['skuMap','skuProps','skuRangePrices','priceRanges','productInfo','offer','offerInfo','images','videos','video','shippingInfo'];
    var maxScriptSize = options.fast ? FAST_SCRIPT_SIZE : MAX_SCRIPT_SIZE;
    var maxVisited = options.fast ? 1200 : 18000;
    var maxDepth = options.fast ? 4 : 7;
    var scripts = document.querySelectorAll('script');
    for (var i = 0; i < scripts.length; i += 1) {
      var script = scripts[i];
      var text = script.textContent || '';
      if (!text || text.length > maxScriptSize) continue;
      var type = clean(script.getAttribute('type'), 100).toLowerCase();
      var hasTarget = /skuMap|skuProps|skuRangePrices|priceRanges|productInfo|offerInfo|detailImages|window\.__DATA__|window\.iDetailData|__INIT_DATA__/i.test(text);
      if (type === 'application/ld+json') {
        try { jsonLd.push(JSON.parse(text)); } catch (error) {}
        continue;
      }
      if (options.fast && !hasTarget) continue;
      if (type === 'application/json') {
        try { stateRoots.push(JSON.parse(text)); } catch (error) {}
      }
      var assigned = hasTarget ? assignedJson(text, ['window.__DATA__','window.__INIT_DATA__','window.iDetailData','window.__offer_detail__','__NEXT_DATA__']) : null;
      if (assigned) stateRoots.push(assigned);
      keys.forEach(function(key) {
        if (selected[key] !== undefined) return;
        var value = valueAfterKey(text, key);
        if (value !== null) selected[key] = value;
      });
      if (options.fast && (selected.skuMap || selected.skus) && (selected.skuProps || selected.productInfo || selected.offerInfo)) break;
    }

    var aliases = {
      skumap:'skuMap', skumodel:'skuMap', skus:'skus', skudata:'skus',
      skuprops:'skuProps', skuattributes:'skuProps',
      skurangeprices:'skuRangePrices', priceranges:'priceRanges',
      productinfo:'productInfo', offerinfo:'offerInfo', offer:'offer',
      detailimages:'detailImages', descriptionimages:'detailImages',
      videos:'videos', video:'video', shippinginfo:'shippingInfo'
    };
    var visited = 0;
    function scan(value, depth) {
      if (!value || typeof value !== 'object' || depth > maxDepth || visited > maxVisited) return;
      visited += 1;
      Object.keys(value).forEach(function(key) {
        var normalized = String(key).replace(/[^a-z]/gi, '').toLowerCase();
        var target = aliases[normalized];
        if (target && selected[target] === undefined) selected[target] = value[key];
        scan(value[key], depth + 1);
      });
    }
    if (!options.fast || (!selected.skuMap && !selected.skus && !selected.skuProps)) {
      stateRoots.forEach(function(root) { scan(root, 0); });
    }
    return { selected: selected, json_ld: jsonLd.slice(0, 10) };
  }

  function compactRaw(value, depth) {
    depth = depth || 0;
    if (depth > 7 || value === null || value === undefined) return null;
    if (typeof value === 'string') return value.slice(0, 8000);
    if (typeof value !== 'object') return value;
    if (Array.isArray(value)) return value.slice(0, 200).map(function(item) { return compactRaw(item, depth + 1); });
    var output = {};
    Object.keys(value).slice(0, 200).forEach(function(key) { output[key] = compactRaw(value[key], depth + 1); });
    return output;
  }

  function compactRawLite(value) {
    if (!value || typeof value !== 'object') return null;
    var output = {};
    Object.keys(value).slice(0, 30).forEach(function(key) {
      var item = value[key];
      if (item == null) return;
      if (typeof item === 'string') output[key] = item.slice(0, 500);
      else if (Array.isArray(item)) output[key] = { type: 'array', length: item.length };
      else if (typeof item === 'object') output[key] = { type: 'object', keys: Object.keys(item).slice(0, 30) };
      else output[key] = item;
    });
    return output;
  }

  function firstObject() {
    for (var i = 0; i < arguments.length; i += 1) {
      var value = arguments[i];
      if (value && typeof value === 'object' && !Array.isArray(value)) return value;
    }
    return {};
  }

  function firstValue() {
    for (var i = 0; i < arguments.length; i += 1) {
      if (arguments[i] !== undefined && arguments[i] !== null && arguments[i] !== '') return arguments[i];
    }
    return '';
  }

  function meta(name) {
    var element = document.querySelector('meta[property="' + name + '"],meta[name="' + name + '"]');
    return element ? clean(element.getAttribute('content'), 4000) : '';
  }

  function merchantTitlePenalty(value) {
    var text = clean(value, 500);
    if (!text) return 0;
    var score = 0;
    if (/有限公司|责任公司|股份公司|工贸|贸易|商行|店铺|旗舰店|实力工厂|源头厂家|自有工厂|跨境货源/.test(text)) score += 45;
    if (/^[\u4e00-\u9fa5]{2,18}(有限公司|工贸有限公司|贸易有限公司)$/.test(text)) score += 45;
    return score;
  }

  function productTitleBonus(value) {
    var text = clean(value, 500);
    var score = 0;
    if (/钓鱼钳|鱼钳|路亚钳|开环|剪线|鱼钩|渔具|fishing|pliers|multi-functional/i.test(text)) score += 55;
    if (/批发|跨境|现货|一件代发|厂家直销|货源/.test(text)) score -= 12;
    if (text.length >= 8 && text.length <= 120) score += 18;
    if (text.length > 160) score -= 18;
    return score;
  }

  function addTitleCandidate(list, value, source, priority) {
    var text = clean(value, 500);
    if (!text || list.some(function(item) { return item.text === text; })) return;
    if (/^(1688|阿里巴巴|商品详情|店铺首页)$/i.test(text)) return;
    list.push({
      text: text,
      source: source,
      score: Number(priority || 0) + productTitleBonus(text) - merchantTitlePenalty(text)
    });
  }

  function bestProductTitle(productInfo, jsonProduct, titleElement) {
    var candidates = [];
    addTitleCandidate(candidates, productInfo.title, 'productInfo.title', 80);
    addTitleCandidate(candidates, productInfo.subject, 'productInfo.subject', 78);
    addTitleCandidate(candidates, productInfo.offerTitle, 'productInfo.offerTitle', 76);
    addTitleCandidate(candidates, jsonProduct.name, 'jsonLd.name', 70);
    addTitleCandidate(candidates, titleElement && titleElement.textContent, 'titleElement', 68);
    [
      '.module-od-title .title-content h1',
      '.module-od-title .title-content',
      '.module-od-title h1'
    ].forEach(function(selector, index) {
      document.querySelectorAll(selector).forEach(function(element) {
        addTitleCandidate(candidates, element.textContent, selector, 100 - index);
      });
    });
    [
      'h1[data-pl="product-title"]',
      '[data-testid="productTitle"]',
      '[class*="title--wrap"] h1',
      '[class*="product-title"]',
      '.offer-title',
      '.mod-detail-title .title',
      '.title-text',
      'h1'
    ].forEach(function(selector, index) {
      document.querySelectorAll(selector).forEach(function(element) {
        addTitleCandidate(candidates, element.textContent, selector, 66 - index);
      });
    });
    addTitleCandidate(candidates, meta('og:title'), 'og:title', 44);
    addTitleCandidate(candidates, document.title && document.title.split(/\s+-\s+阿里巴巴|[-_—|]/)[0], 'document.title', 86);
    candidates.sort(function(a, b) { return b.score - a.score; });
    var best = candidates[0];
    if (!best || best.score < 30) return '';
    return best.text;
  }

  function collectImageElements(selectors, limit) {
    var images = [];
    selectors.forEach(function(selector) {
      document.querySelectorAll(selector).forEach(function(image) {
        if (images.length >= limit) return;
        var width = image.naturalWidth || image.width || 0;
        var height = image.naturalHeight || image.height || 0;
        if ((width && width < 80) || (height && height < 80)) return;
        pushUnique(images, image.currentSrc || image.getAttribute('src') || image.getAttribute('data-src') || image.getAttribute('data-lazy-src') || image.getAttribute('data-ks-lazyload'));
      });
    });
    return images.slice(0, limit);
  }

  function addAttribute(list, name, value) {
    var key = clean(name, 120).replace(/[:：]$/, '');
    var itemValue = clean(value, 500);
    if (!key || !itemValue || key === itemValue) return;
    if (!list.some(function(item) { return item.name === key && item.value === itemValue; })) list.push({ name: key, value: itemValue });
  }

  function collectAttributes(options) {
    options = options || {};
    var attributes = [];
    var maxAttributes = options.fast ? 40 : 200;
    var selectors = ['.offer-attr-item','.mod-detail-attributes li','.detail-attribute li','[class*="offer-attr"] [class*="item"]','[class*="attribute"] li','[class*="property"] li','[class*="param"] li','table tr'];
    selectors.forEach(function(selector) {
      document.querySelectorAll(selector).forEach(function(element) {
        if (attributes.length >= maxAttributes) return;
        var cells = element.querySelectorAll('th,td');
        if (cells.length >= 2) { addAttribute(attributes, cells[0].textContent, cells[1].textContent); return; }
        var label = element.querySelector('dt,[class*="label"],[class*="name"],[class*="key"]');
        var value = element.querySelector('dd,[class*="value"],[class*="text"],[class*="content"]');
        if (label && value && label !== value) { addAttribute(attributes, label.textContent, value.textContent); return; }
        var text = clean(element.textContent, 700);
        var match = text.match(/^([^:：]{1,80})[:：]\s*(.{1,500})$/);
        if (match) addAttribute(attributes, match[1], match[2]);
      });
    });
    return attributes.slice(0, maxAttributes);
  }

  function collectPackageMetrics(attributes) {
    var metrics = { length: null, width: null, height: null, weight: null, dimension_unit: '', weight_unit: '' };
    document.querySelectorAll('table').forEach(function(table) {
      var headers = Array.prototype.slice.call(table.querySelectorAll('thead th,thead td')).map(function(cell) {
        return clean(cell.textContent, 80);
      });
      if (!headers.length || !headers.some(function(name) { return /重量|毛重|长度|宽度|高度|尺寸/i.test(name); })) return;
      var row = table.querySelector('tbody tr');
      if (!row) return;
      var values = Array.prototype.slice.call(row.querySelectorAll('td,th')).map(function(cell) {
        return clean(cell.textContent, 120);
      });
      headers.forEach(function(header, index) {
        var number = numberOrNull(values[index]);
        if (number === null) return;
        var unitMatch = header.match(/[（(]\s*(kg|g|克|千克|mm|cm|m|毫米|厘米|米)\s*[）)]/i);
        var unit = unitMatch ? unitMatch[1].toLowerCase() : '';
        if (/重量|毛重/i.test(header)) {
          metrics.weight = number;
          metrics.weight_unit = unit || 'g';
        } else if (/长度|长\b/i.test(header)) {
          metrics.length = number;
          metrics.dimension_unit = unit || metrics.dimension_unit;
        } else if (/宽度|宽\b/i.test(header)) {
          metrics.width = number;
          metrics.dimension_unit = unit || metrics.dimension_unit;
        } else if (/高度|高\b/i.test(header)) {
          metrics.height = number;
          metrics.dimension_unit = unit || metrics.dimension_unit;
        }
      });
    });
    if (metrics.weight !== null) addAttribute(attributes, '包装重量', metrics.weight + ' ' + (metrics.weight_unit || 'g'));
    if (metrics.length !== null && metrics.width !== null && metrics.height !== null) {
      addAttribute(attributes, '包装尺寸', [metrics.length, metrics.width, metrics.height].join(' x ') + ' ' + (metrics.dimension_unit || 'mm'));
    }
    return metrics;
  }

  function normalizeSkuDimensions(raw) {
    var list = Array.isArray(raw) ? raw : [];
    return list.map(function(item) {
      var values = item.values || item.value || item.options || item.children || [];
      return {
        name: clean(item.name || item.prop || item.propName || item.title || item.attributeName, 100),
        values: (Array.isArray(values) ? values : []).map(function(value) {
          if (typeof value === 'string') return { name: clean(value, 150), id: '', image: '' };
          return {
            name: clean(value.name || value.value || value.text || value.title, 150),
            id: clean(value.id || value.valueId || value.specId || value.propValueId, 100),
            image: mediaUrl(value.image || value.imageUrl || value.picUrl || value.src)
          };
        }).filter(function(value) { return value.name; })
      };
    }).filter(function(item) { return item.name && item.values.length; });
  }

  function normalizeSkuCombinations(selected, dimensions) {
    var result = [];
    var valueMap = {};
    function firstAttributeImage(attributes) {
      var item = (attributes || []).find(function(attribute) { return attribute && attribute.image; });
      return item ? item.image : '';
    }
    dimensions.forEach(function(dimension) {
      dimension.values.forEach(function(value) {
        if (value.id) valueMap[value.id] = { name: dimension.name, value: value.name, source_id: value.id, image: value.image || '' };
      });
    });
    function add(raw, key) {
      if (!raw || typeof raw !== 'object') return;
      var attributes = raw.attributes || raw.properties || raw.props || [];
      if (!Array.isArray(attributes) && attributes && typeof attributes === 'object') {
        attributes = Object.keys(attributes).map(function(name) { return { name: name, value: attributes[name] }; });
      }
      attributes = (Array.isArray(attributes) ? attributes : []).map(function(item) {
        return {
          name: clean(item.name || item.key || item.prop || item.propertyName, 100),
          value: clean(item.value || item.text || item.valueName || item.propertyValue, 150),
          source_id: clean(item.id || item.valueId || item.specId, 100),
          image: mediaUrl(item.image || item.imageUrl || item.picUrl || item.src)
        };
      }).filter(function(item) { return item.name || item.value; });
      if (!attributes.length && key) {
        var ids = String(key).match(/[A-Za-z0-9_-]{2,}/g) || [];
        attributes = ids.map(function(id) { return valueMap[id] || null; }).filter(Boolean);
        if (!attributes.length) attributes = [{ name: '', value: clean(key, 300), source_id: '' }];
      }
      result.push({
        sku_id: clean(raw.skuId || raw.sku_id || raw.id || key, 150),
        sku_code: clean(raw.skuCode || raw.code || raw.specId, 150),
        attributes: attributes,
        price: numberOrNull(firstValue(raw.price, raw.discountPrice, raw.salePrice, raw.unitPrice, raw.skuPrice)),
        inventory: numberOrNull(firstValue(raw.inventory, raw.stock, raw.canBookCount, raw.amountOnSale, raw.quantity)),
        image: mediaUrl(raw.image || raw.imageUrl || raw.picUrl || raw.variantImageUrl) || firstAttributeImage(attributes)
      });
    }
    var list = selected.skus;
    if (Array.isArray(list)) list.forEach(function(item) { add(item, ''); });
    var map = selected.skuMap;
    if (map && typeof map === 'object' && !Array.isArray(map)) Object.keys(map).forEach(function(key) { add(map[key], key); });
    return result;
  }

  function collectDomSkuData(basePrice) {
    var dimensions = [];
    var seenFeature = [];
    document.querySelectorAll('.module-od-sku-selection .feature-item,[class*="sku-selection"] .feature-item').forEach(function(feature) {
      if (seenFeature.indexOf(feature) >= 0) return;
      seenFeature.push(feature);
      var nameNode = feature.querySelector('.feature-item-label,[class*="feature-item-label"],[class*="prop-name"],[class*="sku-title"]');
      var name = clean(nameNode && nameNode.textContent, 80) || '规格';
      if (/^(购买数量|采购数量|订购数量|起订量|数量|价格|单价|总价)$/i.test(name)) return;
      var values = [];
      var itemNodes = feature.querySelectorAll('.expand-view-item,[class*="sku-item"],[class*="expand-view-item"]');
      itemNodes.forEach(function(item) {
        var labelNode = item.querySelector('.item-label,[class*="item-label"],[title]');
        var rawLabel = clean((labelNode && (labelNode.getAttribute('title') || labelNode.textContent)) || item.textContent, 160);
        var valueName = clean(rawLabel.replace(/[¥￥]\s*\d[\s\S]*$/,'').replace(/库存[\s\S]*$/,'').replace(/已售[\s\S]*$/,''), 120);
        if (!valueName || valueName === name || values.some(function(v) { return v.name === valueName; })) return;
        var stockMatch = clean(item.textContent, 300).match(/库存\s*(\d+)/);
        var priceMatch = clean(item.textContent, 300).match(/[¥￥]\s*(\d+(?:\.\d+)?)/);
        var img = item.querySelector('img');
        values.push({
          name: valueName,
          id: '',
          image: mediaUrl(img && (img.currentSrc || img.src || img.getAttribute('data-src'))),
          price: priceMatch ? numberOrNull(priceMatch[1]) : null,
          inventory: stockMatch ? parseInt(stockMatch[1], 10) : null
        });
      });
      if (!values.length) {
        var text = clean(feature.textContent, 1200);
        var pattern = /([\u4e00-\u9fa5A-Za-z0-9#._-]{1,40})\s*库存\s*(\d+)/g;
        var match;
        while ((match = pattern.exec(text)) && values.length < 80) {
          var value = clean(match[1], 80);
          if (value && value !== name && !values.some(function(v) { return v.name === value; })) {
            values.push({ name: value, id: '', image: '', price: basePrice || null, inventory: parseInt(match[2], 10) });
          }
        }
      }
      if (values.length) {
        dimensions.push({ name: name, values: values.slice(0, 80) });
      }
    });
    if (!dimensions.length) {
      return {
        dimensions: [],
        combinations: [{
          sku_id: offerId(),
          sku_code: offerId(),
          attributes: [],
          price: basePrice,
          inventory: null,
          image: ''
        }]
      };
    }
    var combos = [{ attributes: [], price: basePrice || null, inventory: null, image: '' }];
    dimensions.forEach(function(dimension) {
      var next = [];
      combos.forEach(function(combo) {
        dimension.values.forEach(function(value) {
          if (next.length >= 160) return;
          next.push({
            attributes: combo.attributes.concat([{ name: dimension.name, value: value.name, source_id: value.id || '', image: value.image || '' }]),
            price: value.price != null ? value.price : combo.price,
            inventory: value.inventory != null ? value.inventory : combo.inventory,
            image: combo.image || value.image || ''
          });
        });
      });
      combos = next;
    });
    var combinations = combos.map(function(combo, index) {
      var suffix = combo.attributes.map(function(item) { return item.value; }).filter(Boolean).join('-') || String(index + 1);
      return {
        sku_id: offerId() + '-' + suffix,
        sku_code: offerId() + '-' + suffix,
        attributes: combo.attributes,
        price: combo.price != null ? combo.price : basePrice,
        inventory: combo.inventory,
        image: combo.image
      };
    });
    return {
      dimensions: dimensions.map(function(dimension) {
        return {
          name: dimension.name,
          values: dimension.values.map(function(value) {
            return { name: value.name, id: value.id || '', image: value.image || '' };
          })
        };
      }),
      combinations: combinations
    };
  }

  function normalizePriceRanges(raw) {
    var list = Array.isArray(raw) ? raw : [];
    return list.map(function(item) {
      return { minimum_quantity: numberOrNull(firstValue(item.minimum_quantity, item.startQuantity, item.start, item.beginAmount, item.minQuantity)), price: numberOrNull(firstValue(item.price, item.value, item.unitPrice)) };
    }).filter(function(item) { return item.price !== null; });
  }

  function collectVideos(selected) {
    var videos = [];
    pushUnique(videos, meta('og:video'));
    pushUnique(videos, meta('og:video:url'));
    document.querySelectorAll('video,video source').forEach(function(element) { pushUnique(videos, element.currentSrc || element.src || element.getAttribute('src')); });
    function scan(value, depth) {
      if (value == null || depth > 7) return;
      if (typeof value === 'string') {
        if (/^(?:https?:)?\/\//i.test(value) && /(?:\.mp4|\.webm|\.mov|video)/i.test(value)) pushUnique(videos, value);
        return;
      }
      if (Array.isArray(value)) {
        value.slice(0, 100).forEach(function(item) { scan(item, depth + 1); });
        return;
      }
      if (typeof value !== 'object') return;
      pushUnique(videos, value.url || value.videoUrl || value.video_url || value.playUrl || value.play_url || value.src);
      Object.keys(value).slice(0, 120).forEach(function(key) { scan(value[key], depth + 1); });
    }
    scan(selected.videos, 0);
    scan(selected.video, 0);
    try {
      performance.getEntriesByType('resource').forEach(function(entry) {
        var url = entry && entry.name;
        if (url && /(?:\.mp4|\.webm|\.mov)(?:\?|$)/i.test(url)) pushUnique(videos, url);
      });
    } catch (error) {}
    return videos.slice(0, 20);
  }

  function collectDescription(options) {
    options = options || {};
    if (options.fast) return '';
    var selectors = ['#desc-lazyload-container','.desc-lazyload-container','.detail-description-content','.detail-desc','.offer-detail','[class*="description"]','[class*="detail-content"]'];
    var chunks = [];
    selectors.forEach(function(selector) {
      document.querySelectorAll(selector).forEach(function(element) {
        if (options.fast && chunks.length >= 2) return;
        var text = clean(element.innerText || element.textContent, options.fast ? 1200 : 3000);
        if (text.length >= 12 && chunks.indexOf(text) === -1) chunks.push(text);
      });
    });
    return clean(chunks.join('。'), options.fast ? 2200 : 8000);
  }

  function collectShippingText() {
    var selectors = ['[class*="delivery"]','[class*="shipping"]','[class*="logistics"]','[class*="send-address"]','[class*="freight"]'];
    var parts = [];
    selectors.forEach(function(selector) {
      document.querySelectorAll(selector).forEach(function(element) {
        var text = clean(element.textContent, 500);
        if (text && text.length < 500 && parts.indexOf(text) === -1) parts.push(text);
      });
    });
    return clean(parts.join('；'), 1000);
  }

  function extractProduct(options) {
    options = options || {};
    var fast = options.fast !== false;
    var startedAt = Date.now();
    var embedded = collectEmbeddedData({ fast: fast });
    var selected = embedded.selected;
    var productInfo = firstObject(selected.productInfo, selected.offerInfo, selected.offer);
    var jsonProduct = embedded.json_ld.find(function(item) { return item && (item['@type'] === 'Product' || (Array.isArray(item['@graph']) && item['@graph'].length)); }) || {};
    if (Array.isArray(jsonProduct['@graph'])) jsonProduct = jsonProduct['@graph'].find(function(item) { return item && item['@type'] === 'Product'; }) || jsonProduct;

    var titleElement = document.querySelector('.module-od-title .title-content h1,.module-od-title .title-content,.module-od-title h1,h1[data-pl="product-title"],[data-testid="productTitle"],[class*="title--wrap"] h1,.mod-detail-title .title,.title-text,h1');
    var title = bestProductTitle(productInfo, jsonProduct, titleElement);
    if (/1688|阿里巴巴/.test(title) && title.length < 12) title = '';

    var gallery = [];
    var candidateImages = firstValue(productInfo.images, productInfo.image, selected.images, jsonProduct.image, []);
    (Array.isArray(candidateImages) ? candidateImages : [candidateImages]).forEach(function(item) { pushUnique(gallery, imageValue(item)); });
    collectImageElements(['.module-od-gallery .preview-img','.od-gallery-preview img','.detail-gallery img','[data-testid="productImage"] img','.mod-detail-gallery img','[class*="gallery"] .preview-img','[class*="gallery"] img','img[data-role="main-img"]'], fast ? 18 : 100).forEach(function(url) { pushUnique(gallery, url); });
    pushUnique(gallery, meta('og:image'));

    var detailImages = collectImageElements(['#desc-lazyload-container img','.desc-lazyload-container img','.detail-description-content img','.detail-desc img','.offer-detail img','[class*="description"] img'], fast ? 12 : 200);
    var selectedDetailImages = selected.detailImages;
    if (Array.isArray(selectedDetailImages)) selectedDetailImages.slice(0, fast ? 12 : 200).forEach(function(item) { pushUnique(detailImages, typeof item === 'string' ? item : item.url || item.src); });

    var attributes = collectAttributes({ fast: fast });
    var packageMetrics = collectPackageMetrics(attributes);
    var priceElement = document.querySelector('[data-testid="price"],.mod-detail-price .price,[class*="price"] [class*="amount"],[class*="Price"]');
    var price = numberOrNull(firstValue(productInfo.price, productInfo.offerPrice, productInfo.minPrice, jsonProduct.offers && jsonProduct.offers.price, priceElement && priceElement.textContent));
    var priceRanges = normalizePriceRanges(selected.skuRangePrices || selected.priceRanges || productInfo.priceRanges || []);
    if (price === null && priceRanges.length) {
      price = Math.min.apply(null, priceRanges.map(function(item) { return item.price; }));
    }
    var dimensions = normalizeSkuDimensions(selected.skuProps || productInfo.skuProps || []);
    var combinations = normalizeSkuCombinations({ skuMap: selected.skuMap || productInfo.skuMap, skus: selected.skus || productInfo.skus }, dimensions);
    if (!combinations.length) {
      var domSku = collectDomSkuData(price);
      if (!dimensions.length) dimensions = domSku.dimensions;
      combinations = domSku.combinations;
    }
    var shippingText = fast ? '' : collectShippingText();
    var inventoryMatch = fast ? null : clean(document.body.innerText, 200000).match(/(?:库存|可售)\s*[:：]?\s*(\d+)/);
    var deliveryMatch = shippingText.match(/(?:发货|交期|出货)[^；。]{0,60}/);
    var shipFromMatch = shippingText.match(/(?:发货地|发货地址|从)[^；。]{0,80}/);

    return {
      offer_id: offerId(),
      draft_id: draftId(),
      source_platform: '1688',
      url: 'https://detail.1688.com/offer/' + offerId() + '.html',
      title: title,
      name: title,
      main_image: gallery[0] || '',
      gallery_images: gallery.slice(0, fast ? 18 : 100),
      detail_images: detailImages.slice(0, fast ? 12 : 200),
      video_urls: collectVideos(selected),
      price: price,
      currency: 'CNY',
      price_ranges: priceRanges,
      sku_dimensions: dimensions,
      sku_combinations: combinations,
      attributes: attributes,
      package_weight: packageMetrics.weight === null ? '' : packageMetrics.weight + ' ' + (packageMetrics.weight_unit || 'g'),
      package_dimensions: packageMetrics.length !== null && packageMetrics.width !== null && packageMetrics.height !== null
        ? [packageMetrics.length, packageMetrics.width, packageMetrics.height].join(' x ') + ' ' + (packageMetrics.dimension_unit || 'mm')
        : '',
      inventory: inventoryMatch ? parseInt(inventoryMatch[1],10) : null,
      inventory_text: inventoryMatch ? inventoryMatch[0] : '',
      shipping_info: shippingText,
      ship_from: shipFromMatch ? shipFromMatch[0] : '',
      delivery_time: deliveryMatch ? deliveryMatch[0] : '',
      description_text: collectDescription({ fast: fast }),
      raw_page_data: {
        page_title: document.title,
        meta: { title: meta('og:title'), image: meta('og:image'), description: meta('description') },
        json_ld: fast ? compactRawLite(embedded.json_ld) : compactRaw(embedded.json_ld),
        embedded: fast ? compactRawLite(selected) : compactRaw(selected),
        fast_mode: fast
      },
      collected_at: new Date().toISOString(),
      collector_version: COLLECTOR_VERSION,
      collector_mode: fast ? 'fast' : 'full',
      extract_elapsed_ms: Date.now() - startedAt
    };
  }

  function toast(message, type) {
    var old = document.getElementById('qydz-1688-toast');
    if (old) old.remove();
    var element = document.createElement('div');
    element.id = 'qydz-1688-toast';
    element.textContent = message;
    element.style.cssText = 'position:fixed;top:20px;right:20px;z-index:2147483647;max-width:380px;padding:11px 16px;border-radius:5px;color:#fff;background:' + (type === 'error' ? '#b42318' : type === 'warning' ? '#9a6700' : '#087f5b') + ';font:14px/1.5 Microsoft YaHei,sans-serif;box-shadow:0 8px 24px rgba(0,0,0,.2)';
    document.documentElement.appendChild(element);
    setTimeout(function() { element.remove(); }, 3500);
  }

  function escapeHtml(value) {
    return String(value == null ? '' : value).replace(/[&<>"']/g, function(char) {
      return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[char];
    });
  }

  function aiPremiumUrl(value) {
    var raw = clean(value, 2000);
    if (!raw) return '';
    try {
      var url = new URL(raw, PANDA_APP_HOST);
      if (!/^(sczfai\.com|www\.sczfai\.com|8\.137\.211\.255)$/.test(url.hostname)) return '';
      url.searchParams.set('embedded', '1');
      url.searchParams.set('from_plugin', '1');
      url.searchParams.set('v', '5229');
      return url.href;
    } catch (error) {
      return '';
    }
  }

  function instantAiPremiumUrl(product) {
    var url = new URL(PANDA_APP_HOST + '/pages/ai-premium-listing.html');
    url.searchParams.set('entry', 'plugin');
    url.searchParams.set('embedded', '1');
    url.searchParams.set('from_plugin', '1');
    url.searchParams.set('instant', '1');
    url.searchParams.set('v', '5229');
    if (product && product.url) url.searchParams.set('source_url', product.url);
    if (product && product.offer_id) url.searchParams.set('offer_id', product.offer_id);
    return url.href;
  }

  function postFrameMessage(frame, message) {
    if (!frame || !frame.contentWindow) return;
    try { frame.contentWindow.postMessage(message, PANDA_APP_HOST); } catch (error) {}
  }

  function sendProductToFrame(frame, product) {
    if (!product) return;
    postFrameMessage(frame, {
      source: 'qydz-panda-plugin',
      action: 'syncLocalSourceSnapshot',
      product: product
    });
  }

  function sendAuthToFrame(frame, product) {
    if (!frame || !frame.contentWindow || typeof chrome === 'undefined' || !chrome.runtime) return;
    chrome.runtime.sendMessage({ action: 'getPandaAuth' }, function(response) {
      if (chrome.runtime.lastError || !response || !response.token || !frame.contentWindow) {
        sendProductToFrame(frame, product);
        return;
      }
      var count = 0;
      var timer = setInterval(function() {
        count += 1;
        postFrameMessage(frame, {
          source: 'qydz-panda-plugin',
          action: 'syncPandaAuth',
          token: response.token,
          user: response.user || null
        });
        sendProductToFrame(frame, product);
        if (count >= 8) clearInterval(timer);
      }, 350);
    });
  }

  function notifyDraftSaved(response) {
    var frame = window.__QYDZ_AI_PREMIUM_IFRAME__;
    if (!frame || !response) return;
    postFrameMessage(frame, {
      source: 'qydz-panda-plugin',
      action: 'syncDraftSaved',
      draft_id: response.draft_id || '',
      open_url: response.open_url || ''
    });
  }

  function startFrameProductSync(frame, product) {
    if (!product) return;
    var count = 0;
    var timer = setInterval(function() {
      count += 1;
      sendProductToFrame(frame, product);
      if (count >= 30) clearInterval(timer);
    }, 150);
    sendProductToFrame(frame, product);
  }

  function showAiPremiumFrame(url, message, product) {
    var root = document.getElementById('qydz-ai-premium-frame');
    if (!root) {
      root = document.createElement('div');
      root.id = 'qydz-ai-premium-frame';
      root.style.cssText = 'position:fixed;inset:24px;z-index:2147483646;background:rgba(15,23,42,.46);font:14px/1.5 Microsoft YaHei,Arial,sans-serif;display:flex;align-items:center;justify-content:center';
      root.innerHTML = '<div style="width:min(1280px,96vw);height:min(860px,92vh);background:#fff;border-radius:14px;box-shadow:0 24px 80px rgba(15,23,42,.32);display:flex;flex-direction:column;overflow:hidden">'+
        '<div style="height:48px;background:#0f172a;color:#fff;display:flex;align-items:center;justify-content:space-between;padding:0 14px 0 18px">'+
          '<div style="font-weight:700">熊猫 AI 精铺上品</div>'+
          '<div style="display:flex;align-items:center;gap:8px">'+
            '<a id="qydz-ai-premium-open" href="#" target="_blank" style="height:30px;line-height:30px;padding:0 10px;border-radius:7px;background:#2563eb;color:#fff;text-decoration:none;font-size:12px">新窗口打开</a>'+
            '<button id="qydz-ai-premium-close" type="button" style="height:30px;width:32px;border:0;border-radius:7px;background:#334155;color:#fff;cursor:pointer">×</button>'+
          '</div>'+
        '</div>'+
        '<div id="qydz-ai-premium-body" style="flex:1;background:#f8fafc;position:relative"></div>'+
      '</div>';
      document.documentElement.appendChild(root);
      root.querySelector('#qydz-ai-premium-close').onclick = function() { root.remove(); };
      root.addEventListener('click', function(event) {
        if (event.target === root) root.remove();
      });
    }
    var body = root.querySelector('#qydz-ai-premium-body');
    var openLink = root.querySelector('#qydz-ai-premium-open');
    var target = aiPremiumUrl(url);
    if (!target) {
      if (openLink) openLink.removeAttribute('href');
      body.innerHTML = '<div style="height:100%;display:flex;align-items:center;justify-content:center;color:#334155;font-size:15px">'+
        '<div style="text-align:center"><div style="font-weight:700;margin-bottom:8px">'+escapeHtml(message || '正在准备 AI 精铺上品')+'</div><div style="color:#64748b">请稍等，正在采集当前1688商品数据。</div></div>'+
      '</div>';
      return;
    }
    if (openLink) openLink.href = target;
    body.innerHTML = '<iframe id="qydz-ai-premium-iframe" src="'+escapeHtml(target)+'" style="width:100%;height:100%;border:0;background:#fff" allow="clipboard-read;clipboard-write"></iframe>'+
      '<div style="position:absolute;left:16px;bottom:12px;color:#64748b;font-size:12px;background:rgba(255,255,255,.86);padding:4px 8px;border-radius:999px">当前页弹窗模式</div>';
    var frame = body.querySelector('#qydz-ai-premium-iframe');
    window.__QYDZ_AI_PREMIUM_IFRAME__ = frame;
    frame.addEventListener('load', function() {
      sendAuthToFrame(frame, product);
      startFrameProductSync(frame, product);
    });
    sendAuthToFrame(frame, product);
    startFrameProductSync(frame, product);
  }

  function cacheLocally(product) {
    chrome.runtime.sendMessage({ action: 'cacheScrapeData', data: product }, function() {});
  }

  function preloadedProduct() {
    var cached = window.__QYDZ_1688_PRELOAD_PRODUCT__;
    if (!cached || cached.offer_id !== offerId()) return null;
    if (Date.now() - Number(window.__QYDZ_1688_PRELOAD_AT__ || 0) > PRELOAD_MAX_AGE) return null;
    return cached;
  }

  function schedulePrecollect() {
    if (window.__QYDZ_1688_PRELOAD_TIMER__ || window.__QYDZ_1688_PRELOAD_RUNNING__) return;
    var run = function() {
      window.__QYDZ_1688_PRELOAD_TIMER__ = null;
      if (window.__QYDZ_1688_PRELOAD_RUNNING__) return;
      window.__QYDZ_1688_PRELOAD_RUNNING__ = true;
      try {
        var product = extractProduct({ fast: true });
        if (product && product.title) {
          window.__QYDZ_1688_PRELOAD_PRODUCT__ = product;
          window.__QYDZ_1688_PRELOAD_AT__ = Date.now();
        }
      } catch (error) {}
      window.__QYDZ_1688_PRELOAD_RUNNING__ = false;
    };
    if (typeof requestIdleCallback === 'function') {
      window.__QYDZ_1688_PRELOAD_TIMER__ = requestIdleCallback(run, { timeout: 3500 });
    } else {
      window.__QYDZ_1688_PRELOAD_TIMER__ = setTimeout(run, 1600);
    }
  }

  function sendProduct(product, options) {
    options = options || {};
    if (!product.title) { toast('未读取到商品标题，请等待页面加载后重试', 'error'); return; }
    var sentAt = Date.now();
    chrome.runtime.sendMessage({ action: 'forwardScrapeData', data: product, draft_id: product.draft_id }, function(response) {
      if (chrome.runtime.lastError) {
        cacheLocally(product);
        toast('采集结果已暂存，连接恢复后可重试', 'warning');
        return;
      }
      if (response && response.success) {
        var elapsed = ((Date.now() - sentAt + Number(product.extract_elapsed_ms || 0)) / 1000).toFixed(1);
        toast((response.message || '货源快照已保存') + '，耗时' + elapsed + '秒', 'success');
        if (options.instantOpen) {
          notifyDraftSaved(response);
        } else if (options.openAfterSuccess && response.open_url) {
          setTimeout(function() { showAiPremiumFrame(response.open_url); }, 260);
        }
      } else {
        cacheLocally(product);
        toast(response && response.message ? response.message : '回传失败，结果已暂存', 'warning');
        if (options.openAfterSuccess && response && response.login_url) {
          setTimeout(function() { showAiPremiumFrame(response.login_url, '请先登录熊猫商家后台'); }, 360);
        }
      }
    });
  }

  function collectNow(options) {
    options = options || {};
    toast(options.openAfterSuccess ? '正在极速采集当前1688商品并创建AI精铺草稿' : '正在读取1688商品数据', 'success');
    setTimeout(function() {
      var cached = options.fast === true ? preloadedProduct() : null;
      var product = cached || extractProduct({ fast: options.fast === true });
      if (options.openAfterSuccess) {
        if (product.title) {
          showAiPremiumFrame(instantAiPremiumUrl(product), '已极速采集，正在打开AI精铺上品', product);
          options.instantOpen = true;
        } else {
          showAiPremiumFrame('', '正在采集当前1688商品');
        }
      }
      sendProduct(product, options);
    }, 20);
  }

  function addButton() {
    if (document.getElementById('qydz-collect-btn')) return;
    var button = document.createElement('button');
    button.id = 'qydz-collect-btn';
    button.type = 'button';
    button.textContent = 'AI精铺上品';
    button.style.cssText = 'position:fixed;right:24px;bottom:28px;z-index:2147483646;height:42px;padding:0 18px;border:0;border-radius:24px;background:linear-gradient(135deg,#1769aa,#0ea5e9);color:#fff;font:700 14px Microsoft YaHei,sans-serif;box-shadow:0 8px 24px rgba(14,105,170,.28);cursor:pointer';
    button.addEventListener('click', function() { collectNow({ openAfterSuccess: true, fast: false }); });
    document.documentElement.appendChild(button);
  }

  function autoCollect() {
    var params;
    try { params = new URL(location.href).searchParams; } catch (error) { return; }
    if (params.get('_qydz_scrape') !== '1' || window.__QYDZ_1688_AUTO_COLLECT_SENT__) return;
    var attempts = 0;
    var delays = [900, 2000, 4000, 7000, 10000];
    function run() {
      attempts += 1;
      var product = extractProduct({ fast: false });
      if (product.title && (product.main_image || product.gallery_images.length)) {
        window.__QYDZ_1688_AUTO_COLLECT_SENT__ = true;
        sendProduct(product);
      } else if (attempts < delays.length) {
        setTimeout(run, delays[attempts]);
      } else {
        toast('页面数据未加载完整，请点击右下角“熊猫采集”重试', 'warning');
      }
    }
    setTimeout(run, delays[0]);
  }

  chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request && request.action === 'scrape1688Product') {
      var product = extractProduct({ fast: false });
      sendResponse({ success: Boolean(product.title), data: product });
      if (product.title) sendProduct(product);
      return true;
    }
  });

  window.__QYDZ_1688_AI_PREMIUM_COLLECT__ = function() {
    collectNow({ openAfterSuccess: true, fast: false });
  };

  addButton();
  schedulePrecollect();
  autoCollect();
})();
