/* prices.jsx — OHLC fetcher via the backend /api/ohlc/:symbol proxy.
   The Alpha Vantage key lives in the API env (ALPHA_VANTAGE_KEY) so it
   does not need to be in browser localStorage. Frontend keeps a localStorage
   cache to reduce backend calls — 12h for daily/weekly/monthly, 10min for
   intraday series (which go stale fast during market hours).
*/

const PRICES_CACHE_PREFIX = "tw:prices:";
const INTRADAY_INTERVALS = new Set(["5min", "15min", "60min"]);
const cacheTtl = (interval) => (INTRADAY_INTERVALS.has(interval) ? 10 * 60_000 : 12 * 3600_000);

function cacheRead(symbol, interval) {
  try {
    const raw = localStorage.getItem(PRICES_CACHE_PREFIX + symbol + "|" + interval);
    if (!raw) return null;
    const { ts, candles, source } = JSON.parse(raw);
    if (Date.now() - ts > cacheTtl(interval)) return null;
    return { candles, source };
  } catch { return null; }
}
function cacheWrite(symbol, interval, candles, source) {
  try {
    localStorage.setItem(PRICES_CACHE_PREFIX + symbol + "|" + interval,
      JSON.stringify({ ts: Date.now(), candles, source }));
  } catch {}
}

// In-flight de-dup (keyed per symbol+interval)
const _inflight = new Map();

async function fetchOHLC(symbol, interval = "daily") {
  const cached = cacheRead(symbol, interval);
  if (cached) return { candles: cached.candles, source: "cache" };

  const fk = symbol + "|" + interval;
  if (_inflight.has(fk)) return _inflight.get(fk);

  const url = apiBase() + "/api/ohlc/" + encodeURIComponent(symbol) + "?interval=" + encodeURIComponent(interval);

  const promise = (async () => {
    try {
      const ctrl = new AbortController();
      const to = setTimeout(() => ctrl.abort(), 10000);
      const r = await fetch(url, { signal: ctrl.signal, credentials: "include" });
      clearTimeout(to);
      const j = await r.json();
      if (!j.candles) {
        return { candles: null, source: "fallback", error: j.error || "no data" };
      }
      cacheWrite(symbol, interval, j.candles, j.source);
      return { candles: j.candles, source: j.source || "alphavantage" };
    } catch (e) {
      return { candles: null, source: "fallback", error: e.message };
    }
  })();

  _inflight.set(fk, promise);
  promise.finally(() => _inflight.delete(fk));
  return promise;
}

// React hook
function useOHLC(symbol, interval = "daily") {
  const [state, setState] = useState({ loading: true, candles: null, source: null, error: null });
  useEffect(() => {
    let cancelled = false;
    setState(s => ({ ...s, loading: true }));
    fetchOHLC(symbol, interval).then(res => {
      if (cancelled) return;
      if (res.candles) {
        setState({ loading: false, candles: res.candles, source: res.source, error: null });
      } else {
        // Fall back to deterministic mock if backend or AV returns nothing
        const mock = generateCandles(symbol, 100);
        setState({ loading: false, candles: mock, source: "mock", error: res.error });
      }
    });
    return () => { cancelled = true; };
  }, [symbol, interval]);
  return state;
}

// Legacy shims so settings.jsx still works without ripping it out — these are now no-ops
function getApiKey() { return "managed-by-backend"; }
function setApiKey() {}

Object.assign(window, { fetchOHLC, useOHLC, getApiKey, setApiKey });
