// 共用 Yahoo Finance cookie/crumb（避免多模組並行請求互相打掛）
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36';

let _auth = { cookie: null, crumb: null, at: 0 };
let _inflight = null;
let _queue = Promise.resolve();

export function resetYahooAuth() {
  _auth = { cookie: null, crumb: null, at: 0 };
}

export async function yahooAuth(force = false) {
  if (!force && _auth.crumb && Date.now() - _auth.at < 3600e3) return _auth;
  if (_inflight) return _inflight;
  _inflight = (async () => {
    const r1 = await fetch('https://fc.yahoo.com/', { headers: { 'User-Agent': UA } }).catch(() => null);
    const cookie = (r1?.headers.get('set-cookie') || '').split(';')[0] || '';
    const r2 = await fetch('https://query2.finance.yahoo.com/v1/test/getcrumb', {
      headers: { 'User-Agent': UA, Cookie: cookie },
    });
    const crumb = (await r2.text()).trim();
    if (!crumb || crumb.includes('<')) throw new Error('Yahoo crumb');
    _auth = { cookie, crumb, at: Date.now() };
    return _auth;
  })().finally(() => { _inflight = null; });
  return _inflight;
}

async function yahooJson(url, retry = true) {
  const { cookie, crumb } = await yahooAuth();
  const sep = url.includes('?') ? '&' : '?';
  const full = `${url}${sep}crumb=${encodeURIComponent(crumb)}`;
  const res = await fetch(full, { headers: { 'User-Agent': UA, Cookie: cookie } });
  if ((res.status === 401 || res.status === 429) && retry) {
    resetYahooAuth();
    await sleep(500);
    await yahooAuth(true);
    return yahooJson(url, false);
  }
  if (!res.ok) throw new Error(`Yahoo HTTP ${res.status}`);
  return res.json();
}

function yahooQueued(fn) {
  const run = _queue.then(() => fn());
  _queue = run.catch(() => {});
  return run;
}

/** quoteSummary 模組（assetProfile、topHoldings 等）— 序列化避免並行打掛 crumb */
export async function yahooQuoteSummary(symbol, modules) {
  return yahooQueued(async () => {
    const mod = Array.isArray(modules) ? modules.join(',') : modules;
    const url = `https://query2.finance.yahoo.com/v10/finance/quoteSummary/${encodeURIComponent(symbol)}?modules=${encodeURIComponent(mod)}`;
    const j = await yahooJson(url);
    await sleep(120);
    return j?.quoteSummary?.result?.[0] || null;
  });
}

export async function yahooFinanceSearchNews(symbol, count = 12) {
  return yahooQueued(async () => {
    const url = `https://query1.finance.yahoo.com/v1/finance/search?q=${encodeURIComponent(symbol)}&newsCount=${count}&quotesCount=0`;
    const j = await yahooJson(url);
    await sleep(120);
    return j?.news || [];
  });
}

export function sleep(ms) {
  return new Promise(r => setTimeout(r, ms));
}