/**
 * Resolve game / catalog item name from numeric ID via main site API only (no direct Roblox fetch in extension).
 */
(function (global) {
  'use strict';

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

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

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

  function getResolveTryOrigins(primary) {
    const g = typeof global !== 'undefined' ? global : window;
    const base = String(primary || '').trim().replace(/\/+$/, '');
    let u;
    try {
      u = new URL(base);
    } catch {
      return g.MRBX_PROBE_LOCAL_FIRST === true
        ? [...LOCAL_SCAN_PORTS.map((p) => 'http://127.0.0.1:' + p), base]
        : [base];
    }
    const 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((p) => 'http://127.0.0.1:' + p), base];
  }

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

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

  function fetchWithTimeout(url, options) {
    const ctrl = new AbortController();
    const t = setTimeout(function () {
      ctrl.abort();
    }, RESOLVE_FETCH_MS);
    return fetch(url, Object.assign({}, options || {}, { signal: ctrl.signal, credentials: 'omit' })).finally(
      function () {
        clearTimeout(t);
      }
    );
  }

  async function resolveViaMainSite(mode, rawDigits) {
    const id = String(rawDigits || '').replace(/\D/g, '');
    if (!id) {
      throw new Error('ID must be numeric.');
    }
    const m = mode === 'clothing' ? 'clothing' : 'game';
    const primary = getPrimaryOrigin();
    const origins = getResolveTryOrigins(primary);
    const body = JSON.stringify({ mode: m, id: id });
    let lastErr;
    for (let i = 0; i < origins.length; i++) {
      const origin = origins[i];
      const url = joinUrl(origin, 'api/resolve-item');
      try {
        const r = await fetchWithTimeout(url, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: body
        });
        const text = await r.text();
        let j = {};
        try {
          j = text ? JSON.parse(text) : {};
        } catch {
          j = {};
        }
        if (r.ok && j.ok && j.name) {
          return String(j.name).trim();
        }
        const errMsg = (j && j.error) || 'Resolve failed (HTTP ' + r.status + ').';
        throw new Error(errMsg);
      } 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);
  }

  var g = typeof globalThis !== 'undefined' ? globalThis : window;
  g['RbxResolve'] = {
    resolveItemName,
    resolveGameNameFromPlaceId,
    resolveNameFromAssetId
  };
})(typeof globalThis !== 'undefined' ? globalThis : window);
