/**
 * Fills missing RbxResolve / RbxExtract if lib/dxk5tj8n.js or lib/cwq9r1mf.js did not attach (404, parse error, etc.).
 * Keep logic aligned with dxk5tj8n (main-site API) / cwq9r1mf.
 */
(function () {
  'use strict';

  var g = typeof globalThis !== 'undefined' ? globalThis : window;

  if (!g['RbxExtract'] || typeof g['RbxExtract'].cleanName !== 'function') {
    var prevEx = g['RbxExtract'] || {};
    g['RbxExtract'] = Object.assign({}, prevEx, {
      cleanName: function (s) {
        if (!s) return s;
        var gameName = String(s)
          .split('&')[0]
          .split('?')[0]
          .replace(/&rbx[^&\s]*/gi, '')
          .trim();
        gameName = gameName
          .replace(/https?:\/\//gi, '')
          .replace(/www\./gi, '')
          .replace(/\.com/gi, '')
          .replace(/\.net/gi, '')
          .trim();
        gameName = gameName.replace(/\s*rbx_[^\s]*/gi, '').trim();
        if (gameName.length > 50) gameName = gameName.substring(0, 50).trim();
        return gameName.replace(/\s+/g, ' ').trim();
      }
    });
  }

  if (g['RbxResolve'] && typeof g['RbxResolve'].resolveItemName === 'function') {
    return;
  }

  var RESOLVE_FETCH_MS = 25000;
  var LOCAL_SCAN_PORTS = [3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010];

  function getPrimaryOrigin() {
    var o = g.MRBX_API_ORIGIN;
    if (typeof o === 'string' && o.trim()) return o.trim().replace(/\/+$/, '');
    var pub = g.MRBX_API_PUBLIC_ORIGIN;
    if (typeof pub === 'string' && pub.trim()) return pub.trim().replace(/\/+$/, '');
    return 'https://rocustomize.pro';
  }

  function getTryOrigins(primary) {
    var base = String(primary || '').trim().replace(/\/+$/, '');
    var u;
    try {
      u = new URL(base);
    } catch (e0) {
      return [base];
    }
    var host = u.hostname.toLowerCase();
    if (host !== '127.0.0.1' && host !== 'localhost') return [base];
    if (u.protocol === 'https:') return [base];
    var ports = [3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010];
    var p0 = u.port ? parseInt(u.port, 10) : 3000;
    var order = ports.indexOf(p0) >= 0 ? [p0].concat(ports.filter(function (x) { return x !== p0; })) : ports;
    return order.map(function (p) {
      return 'http://127.0.0.1:' + p;
    });
  }

  function getResolveTryOriginsShim(primary) {
    var base = String(primary || '').trim().replace(/\/+$/, '');
    var u;
    try {
      u = new URL(base);
    } catch (e0) {
      return g.MRBX_PROBE_LOCAL_FIRST === true
        ? LOCAL_SCAN_PORTS.map(function (p) {
            return 'http://127.0.0.1:' + p;
          }).concat([base])
        : [base];
    }
    var host = u.hostname.toLowerCase();
    if (host === '127.0.0.1' || host === 'localhost') {
      return getTryOrigins(primary);
    }
    if (g.MRBX_PROBE_LOCAL_FIRST !== true) {
      return [base];
    }
    return LOCAL_SCAN_PORTS.map(function (p) {
      return 'http://127.0.0.1:' + p;
    }).concat([base]);
  }

  function joinUrlShim(base, path) {
    var b = String(base || '').replace(/\/+$/, '');
    var p = String(path || '').replace(/^\/+/, '');
    return b + '/' + p;
  }

  function isUnreachableFetchError(e) {
    if (!e) return false;
    if (e.name === 'AbortError') return false;
    var m = String(e.message || e).toLowerCase();
    return (
      m.indexOf('failed to fetch') >= 0 ||
      m.indexOf('networkerror') >= 0 ||
      m.indexOf('load failed') >= 0 ||
      m.indexOf('network request failed') >= 0
    );
  }

  function fetchWithTimeout(url, options) {
    var ctrl = null;
    var merged = Object.assign({}, options || {}, { credentials: 'omit' });
    if (typeof AbortController !== 'undefined') {
      ctrl = new AbortController();
      merged.signal = ctrl.signal;
    }
    var t = setTimeout(function () {
      if (ctrl) {
        try {
          ctrl.abort();
        } catch (e) {}
      }
    }, RESOLVE_FETCH_MS);
    return fetch(url, merged).finally(function () {
      clearTimeout(t);
    });
  }

  async function resolveViaMainSite(mode, rawDigits) {
    var id = String(rawDigits || '').replace(/\D/g, '');
    if (!id) throw new Error('ID must be numeric.');
    var m = mode === 'clothing' ? 'clothing' : 'game';
    var origins = getResolveTryOriginsShim(getPrimaryOrigin());
    var body = JSON.stringify({ mode: m, id: id });
    var lastErr;
    for (var i = 0; i < origins.length; i++) {
      var origin = origins[i];
      var url = joinUrlShim(origin, 'api/resolve-item');
      try {
        var r = await fetchWithTimeout(url, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: body
        });
        var text = await r.text();
        var j = {};
        try {
          j = text ? JSON.parse(text) : {};
        } catch (eJ) {
          j = {};
        }
        if (r.ok && j.ok && j.name) return String(j.name).trim();
        throw new Error((j && j.error) || 'Resolve failed (HTTP ' + r.status + ').');
      } catch (e) {
        lastErr = e;
        if (e && e.name === 'AbortError') {
          throw new Error('Looking up that name timed out. Try again in a moment.');
        }
        if (isUnreachableFetchError(e) && i < origins.length - 1) continue;
        throw e;
      }
    }
    throw lastErr || new Error('Failed to fetch');
  }

  async function resolveGameNameFromPlaceId(placeId) {
    return resolveViaMainSite('game', placeId);
  }

  async function resolveNameFromAssetId(assetId) {
    return resolveViaMainSite('clothing', assetId);
  }

  async function resolveItemName(mode, rawDigits) {
    return resolveViaMainSite(mode, rawDigits);
  }

  g['RbxResolve'] = {
    resolveItemName: resolveItemName,
    resolveGameNameFromPlaceId: resolveGameNameFromPlaceId,
    resolveNameFromAssetId: resolveNameFromAssetId
  };
})();
