"""
MLBB / Philippines (/ph/) only — package selection for smile.one auto_order.

Brazil and other regions keep using order_automation._SELECT_PACKAGE_JS unchanged.
This module is loaded only when product_url contains /ph/.
"""

# Must match scraper_playwright extractSmileCards() UL/LI walk (document order).
PH_PACKAGE_LI_LOCATOR = (
    "ul.PcDiamant-ul > li, ul.commonDiamant-ul > li, .product-list-container ul > li"
)

# Playwright page.evaluate — same argument tuple as _SELECT_PACKAGE_JS:
# [targetBrlCents, targetIndex, targetName, targetLiId, targetPhpCents]
SELECT_PACKAGE_PH_JS = """
([targetBrlCents, targetIndex, targetName, targetLiId, targetPhpCents]) => {
  const allPhpCents = (txt) => {
    const out = [];
    const re = /(?:\\u20b1|₱)\\s*([0-9][0-9.,]*(?:\\.[0-9]{1,2})?)|PHP\\s*([0-9][0-9.,]*(?:\\.[0-9]{1,2})?)/gi;
    let m;
    const s = txt || '';
    while ((m = re.exec(s)) !== null) {
      const raw = String(m[1] || m[2] || '').replace(/,/g, '');
      const n = Number(raw);
      if (!Number.isNaN(n) && n >= 0) out.push(Math.round(n * 100));
    }
    return out;
  };

  const normalize = (s) => (s || '')
    .replace(/[\\u00d7\\u2715\\u2a2f\\u2716]/g, 'x')
    .replace(/[^a-z0-9x+]/gi, '').toLowerCase();

  const normContainsSku = (norm, sku) => {
    if (!sku) return true;
    let pos = norm.indexOf(sku);
    while (pos !== -1) {
      const next = norm.charAt(pos + sku.length);
      if (!(next >= '0' && next <= '9')) return true;
      pos = norm.indexOf(sku, pos + 1);
    }
    return false;
  };

  /** PH/PT smile.one: weekly pass row text often has no English "weekly". */
  const rawIsWeeklyDiamondPassLike = (txt) => {
    const u = String(txt || '').toLowerCase();
    if (/weekly\\s*diamond\\s*pass/.test(u)) return true;
    if (/weekly/.test(u) && /pass/.test(u) && (/diamond|gem|bonus/).test(u)) return true;
    if (/passe\\s+semanal\\s+de\\s+diamante/.test(u)) return true;
    if (/passe\\s+semanal/.test(u) && /diamante/.test(u)) return true;
    if (/semanal\\s+de\\s+diamante/.test(u)) return true;
    return false;
  };

  const targetWantsWeeklyDiamondPass = (txt) => {
    const x = String(txt || '').toLowerCase();
    if (/weekly\\s*diamond\\s*pass/.test(x)) return true;
    if (/weekly/.test(x) && /pass/.test(x) && /diamond/.test(x)) return true;
    if (/passe\\s+semanal\\s+de\\s+diamante/.test(x)) return true;
    if (/passe\\s+semanal/.test(x) && /diamante/.test(x)) return true;
    return false;
  };

  const rawIsBareDiamondTopUp = (txt) => {
    if (rawIsWeeklyDiamondPassLike(txt)) return false;
    const u = String(txt || '').replace(/[\\u00d7\\u2715\\u2a2f\\u2716×]/g, 'x');
    return /diamond\\s*x\\s*\\d{1,7}|diamondx\\d{1,7}|\\d{1,7}\\s+diamonds?\\b/i.test(u);
  };

  const pkgSkuMatches = (raw, norm, targetName) => {
    const t = String(targetName || '').trim();
    if (!t) return true;
    const r = (raw || '').replace(/\\s+/g, ' ').trim();

    // Weekly Pass order must never match a plain ₱ diamond top-up row (same price as pass).
    if (targetWantsWeeklyDiamondPass(t) && rawIsBareDiamondTopUp(r) && !rawIsWeeklyDiamondPassLike(r)) return false;

    const dB = t.match(/Diamondx(\\d{1,7})/i);
    const dA = t.match(/Diamond\\s*[x×\\u00d7\\u2715\\u2a2f\\u2716]\\s*(\\d{1,7})/i);
    const dn = dB ? dB[1] : (dA ? dA[1] : null);
    if (dn) {
      const nb = String(parseInt(dn, 10));
      const r1 = new RegExp('Diamond\\\\s*[\\\\u00d7x\\\\u2715\\\\u2a2f]\\\\s*' + nb + '(?!\\\\d)', 'i');
      const r2 = new RegExp('Diamondx' + nb + '(?!\\\\d)', 'i');
      const flat = r.replace(/[\\u00d7\\u2715\\u2a2f\\u2716×]/g, 'x');
      const hasD = r1.test(r) || r2.test(flat);
      if (!hasD) return false;
      // Plain diamond pack: skip Weekly Pass cards that mention the same Diamond×N in fine print.
      if (!targetWantsWeeklyDiamondPass(t) && rawIsWeeklyDiamondPassLike(r)) return false;
      return true;
    }
    if (/twilight/i.test(t)) return /twilight/i.test(r);
    if (targetWantsWeeklyDiamondPass(t)) return rawIsWeeklyDiamondPassLike(r);

    const nw = /weekly/i.test(t);
    const ne = /elite/i.test(t);
    const nm = /monthly/i.test(t);
    const nxp = /epic/i.test(t);
    if (nw && ne) return /weekly/i.test(r) && /elite/i.test(r);
    if (nm && nxp) return /monthly/i.test(r) && /epic/i.test(r);
    if (nw || ne || nm || nxp) {
      let ok = true;
      if (nw) ok = ok && (/weekly/i.test(r) || rawIsWeeklyDiamondPassLike(r));
      if (ne) ok = ok && /elite/i.test(r);
      if (nm) ok = ok && /monthly/i.test(r);
      if (nxp) ok = ok && /epic/i.test(r);
      return ok;
    }
    return normContainsSku(norm, normalize(t));
  };

  // Same order as scraper extractSmileCards(): UL list then :scope > li (PH rows with ₱).
  const seen = new Set();
  const lis = [];
  const uls = document.querySelectorAll(
    'ul.PcDiamant-ul, ul.commonDiamant-ul, .product-list-container ul'
  );
  for (const ul of uls) {
    try {
      for (const li of ul.querySelectorAll(':scope > li')) {
        const raw0 = (li.innerText || '').replace(/\\s+/g, ' ').trim();
        if (!raw0 || raw0.length > 400) continue;
        if (!/\\u20b1\\s*[\\d]/.test(raw0) && !/PHP\\s*[\\d]/i.test(raw0)) continue;
        if (!seen.has(li)) { seen.add(li); lis.push(li); }
      }
    } catch (e) {}
  }
  const selsFallback = [
    'ul[class*="PcDiamant"] > li', 'ul[class*="pc-diamant" i] > li',
    'ul[class*="commonDiamant"] > li', 'ul[class*="CommonDiamant"] > li',
    '[class*="product-list-container"] ul > li', '[class*="product-list"] ul > li',
    '[class*="goods-list"] li[class*="item" i]', '[class*="recharge"] ul > li',
  ];
  if (!lis.length) {
    for (const sel of selsFallback) {
      try {
        for (const li of document.querySelectorAll(sel)) {
          const raw0 = (li.innerText || '').replace(/\\s+/g, ' ').trim();
          if (!/\\u20b1\\s*[\\d]/.test(raw0) && !/PHP\\s*[\\d]/i.test(raw0)) continue;
          if (!seen.has(li)) { seen.add(li); lis.push(li); }
        }
      } catch (e) {}
    }
  }
  if (!lis.length) {
    const root = document.querySelector('main') || document.querySelector('[class*="merchant"]') || document.body;
    root.querySelectorAll('li[id]').forEach((li) => {
      const t = (li.innerText || '');
      if (t.length > 800) return;
      if (/\\u20b1\\s*[\\d]/.test(t) || /PHP\\s*[\\d]/i.test(t)) {
        if (!seen.has(li)) { seen.add(li); lis.push(li); }
      }
    });
  }
  if (!lis.length) {
    const root = document.querySelector('main') || document.querySelector('[class*="merchant"]') || document.body;
    root.querySelectorAll('[id]').forEach((el) => {
      const tag = (el.tagName || '').toLowerCase();
      if (tag === 'script' || tag === 'style' || tag === 'noscript' || tag === 'link' || tag === 'meta') return;
      const t = (el.innerText || '');
      if (t.length < 4 || t.length > 1200) return;
      if (/\\u20b1\\s*[\\d]/.test(t) || /PHP\\s*[\\d]/i.test(t)) {
        if (!seen.has(el)) { seen.add(el); lis.push(el); }
      }
    });
  }
  if (!lis.length) return { ok: false, reason: 'no_package_lis' };

  const nameLower = normalize(targetName);
  const hasPhpCents = targetPhpCents !== null && targetPhpCents !== undefined;
  const hasAnyPrice = hasPhpCents;

  const rowPhpMatchesTarget = (phpPrices) => {
    if (!hasPhpCents) return true;
    if (!phpPrices || !phpPrices.length) return false;
    if (phpPrices.includes(targetPhpCents)) return true;
    if (phpPrices.length >= 2) {
      const lo = Math.min(...phpPrices);
      const hi = Math.max(...phpPrices);
      return targetPhpCents === lo || targetPhpCents === hi;
    }
    return false;
  };

  const buildPkgs = () => lis.map((li, i) => {
    const raw = (li.innerText || '').replace(/\\s+/g, ' ').trim();
    const phpPrices = allPhpCents(raw);
    return { li, raw, norm: normalize(raw), phpPrices, idx: i, liId: li.id || '' };
  });

  let pkgs = buildPkgs();

  const rowFromEl = (el) => {
    const raw = (el.innerText || '').replace(/\\s+/g, ' ').trim();
    const phpPrices = allPhpCents(raw);
    let idx = lis.indexOf(el);
    if (idx < 0) {
      lis.push(el);
      pkgs = buildPkgs();
      idx = lis.indexOf(el);
    }
    const rec = pkgs.find((p) => p.li === el);
    return { raw, phpPrices, idx, rec };
  };

  // Strict: targetLiId path requires price + name agreement, never trust id alone.
  if (targetLiId) {
    const idStr = String(targetLiId).trim();
    const byId = idStr ? document.getElementById(idStr) : null;
    if (!byId) {
      return { ok: false, reason: 'catalog_li_id_not_found', count: lis.length };
    }
    const { raw, phpPrices, rec } = rowFromEl(byId);
    if (!rec) {
      return { ok: false, reason: 'catalog_li_id_outside_packages', count: lis.length };
    }
    const looksPhp = phpPrices.length > 0 || /\\u20b1\\s*[\\d]/.test(raw) || /PHP\\s*[\\d]/i.test(raw);
    if (!looksPhp) {
      return { ok: false, reason: 'catalog_li_id_mismatch', count: lis.length };
    }
    if (hasPhpCents && !rowPhpMatchesTarget(phpPrices)) {
      return { ok: false, reason: 'catalog_li_id_price_mismatch', count: lis.length };
    }
    const nm = String(targetName || '').trim();
    if (nm && !pkgSkuMatches(raw, rec.norm, targetName)) {
      return { ok: false, reason: 'catalog_li_id_name_mismatch', count: lis.length };
    }
    return {
      ok: true,
      liId: byId.id || rec.liId,
      text: raw.slice(0, 150),
      matchedPrices: [],
      index: rec.idx,
      matchStep: 'catalog_li_id',
    };
  }

  let chosen = null;
  let matchStep = '';

  if (nameLower && hasPhpCents) {
    const matches = pkgs.filter((p) => rowPhpMatchesTarget(p.phpPrices) && pkgSkuMatches(p.raw, p.norm, targetName));
    if (matches.length === 1) {
      chosen = matches[0]; matchStep = 'php_price+name';
    } else if (matches.length > 1 && targetIndex !== null && targetIndex !== undefined && !Number.isNaN(Number(targetIndex))) {
      const ti = Math.max(0, Math.min(pkgs.length - 1, Number(targetIndex)));
      const cand = matches.find((p) => p.idx === ti);
      if (cand) { chosen = cand; matchStep = 'php_price+name+index'; }
    }
  }

  if (!chosen && hasPhpCents) {
    const byPrice = pkgs.filter((p) => rowPhpMatchesTarget(p.phpPrices));
    if (byPrice.length === 1) {
      chosen = byPrice[0]; matchStep = 'unique_php_price';
    }
  }

  if (!chosen && !hasAnyPrice && nameLower) {
    const matches = pkgs.filter((p) => pkgSkuMatches(p.raw, p.norm, targetName));
    if (matches.length === 1) {
      chosen = matches[0]; matchStep = 'name_only_unique';
    }
  }

  if (!chosen) {
    let reason = 'no_match';
    if (hasPhpCents) {
      const n = pkgs.filter((p) => rowPhpMatchesTarget(p.phpPrices)).length;
      if (n > 1) reason = 'ambiguous_php_price';
      else if (n === 0) reason = 'price_not_found';
    }
    return { ok: false, reason, count: lis.length };
  }

  return {
    ok: true,
    liId: chosen.liId,
    text: chosen.raw.slice(0, 150),
    matchedPrices: [],
    index: chosen.idx,
    matchStep
  };
}
"""

# Run before package evaluate() so lazy-loaded PH grids attach <li> nodes.
PH_SCROLL_PRIMING_JS = """
async () => {
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
  window.scrollTo(0, 0);
  await sleep(300);
  for (let i = 0; i < 6; i++) {
    window.scrollBy(0, Math.min(500, (document.body.scrollHeight || 800) / 5));
    await sleep(350);
  }
  window.scrollTo(0, document.body.scrollHeight);
  await sleep(400);
  window.scrollTo(0, 0);
  await sleep(300);
}
"""

# Brazil keeps order_automation._CLICK_PAYMENT_JS — PH uses looser matching + text fallback.
PH_CLICK_PAYMENT_JS = """
() => {
  const cards = Array.from(document.querySelectorAll('[class*="sectionNav-cartao"], [class*="sectionnav-cartao"]'));
  if (!cards.length) return { ok: false, reason: 'no_payment_methods' };
  const low = (s) => (s || '').toLowerCase();
  let sc = cards.find(c => low(c.className).includes('smilecoin'));
  if (!sc) {
    for (const c of cards) {
      const inner = c.querySelector('[class*="smilecoin"], [class*="SmileCoin"]');
      if (inner) { sc = inner; break; }
    }
  }
  if (!sc) {
    sc = cards.find(c => /smile\\s*coin/i.test((c.innerText || '')));
  }
  if (sc) { sc.click(); return { ok: true, method: 'Smile Coin' }; }
  return { ok: false, reason: 'no_smile_coin_option' };
}
"""

# English labels common on /ph/ checkout; Brazil flow does not use this list.
PH_EXTRA_BUY_TEXTS = (
    "Buy now",
    "Buy Now",
    "Purchase",
    "Pay now",
    "Checkout",
    "Place order",
    "Confirm order",
)


def ph_payment_targets(page, sel_ctx):
    """
    Smile Coin + buy bar may render on the same frame as the package (e.g. iframe) or on main page.
    Only used when product_url contains /ph/.
    """
    out: list = []
    try:
        mf = page.main_frame
        if sel_ctx is not mf:
            out.append(sel_ctx)
    except Exception:
        pass
    out.append(page)
    return out
