/* FinPulse — live-data context + Settings modal. Uses FP_API layer. */
function curSym(c) { return window.FinnhubMappers.curSym(c); }

function relTime(unixSec) { return window.FinnhubMappers.relTime(unixSec); }
function mapNews(items) { return window.FinnhubMappers.mapNewsList(items); }
function buildLiveStock(symbol, q, profile, metric) {
  return window.FinnhubMappers.mapStock(symbol, q, profile, metric);
}

function mcapM(m, cur) {
  const s = curSym(cur);
  if (!m || m <= 0) return '—';
  if (m >= 1e6) return s + (m / 1e6).toFixed(2) + 'T';
  if (m >= 1e3) return s + (m / 1e3).toFixed(1) + 'B';
  return s + m.toFixed(0) + 'M';
}

const LiveCtx = React.createContext(null);
function useLive() { return React.useContext(LiveCtx); }

function LiveProvider({ children }) {
  const api = window.FP_API.finnhub;
  const market = window.FP_API.market;
  const [key, setKeyState] = useState(api.getKey());
  const [serverKey, setServerKey] = useState(false);
  const [live, setLive] = useState(() => localStorage.getItem('fp-live') === '1' && api.hasKey());
  const [connected, setConnected] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [rateLimit, setRateLimit] = useState(api.getRateLimit());

  useEffect(() => {
    let on = true;

    async function initFinnhub() {
      try {
        const res = await fetch('/api/config');
        if (res.ok) {
          const cfg = await res.json();
          if (cfg.finnhub && cfg.finnhub.available) {
            api.setServerKeyAvailable(true);
            if (on) setServerKey(true);
            if (localStorage.getItem('fp-live') !== '0') {
              localStorage.setItem('fp-live', '1');
              if (on) setLive(true);
            }
          }
        }
      } catch (_) { /* offline */ }

      if (!on) return;
      if (api.hasKey()) {
        try {
          const ok = await api.test(null);
          if (on) { setConnected(ok); setRateLimit(api.getRateLimit()); }
        } catch (_) {
          if (on) setConnected(false);
        }
      }
    }

    initFinnhub();
    return () => { on = false; };
  }, []);

  function saveKey(k) { api.setKey(k); setKeyState(k); }
  function setLiveMode(v) {
    const on = v && api.hasKey();
    setLive(on);
    localStorage.setItem('fp-live', on ? '1' : '0');
  }

  const value = {
    api,
    market,
    key,
    connected,
    setConnected,
    live: live && connected,
    liveRaw: live,
    hasKey: !!key || serverKey,
    rateLimit,
    refreshRateLimit: () => setRateLimit(api.getRateLimit()),
    saveKey,
    setLiveMode,
    openSettings: () => setSettingsOpen(true),
    closeSettings: () => setSettingsOpen(false),
  };

  return (
    <LiveCtx.Provider value={value}>
      {children}
      {settingsOpen && <SettingsModal />}
    </LiveCtx.Provider>
  );
}

function SettingsModal() {
  const L = useLive();
  const [val, setVal] = useState(L.key || '');
  const [status, setStatus] = useState(L.connected ? 'ok' : 'idle');
  const [statusDetail, setStatusDetail] = useState('');
  const [live, setLiveLocal] = useState(L.liveRaw);

  async function test() {
    setStatus('testing');
    setStatusDetail('');
    try {
      const ok = await L.api.test(val.trim());
      if (ok) { setStatus('ok'); setStatusDetail(''); L.setConnected(true); L.refreshRateLimit(); }
      else { setStatus('bad'); setStatusDetail('Quote returned empty — check key'); L.setConnected(false); }
    } catch (e) {
      const code = e.code || e.message;
      setStatus(code === 'AUTH' ? 'bad' : code === 'NETWORK' ? 'net' : code === 'NO_KEY' ? 'bad' : 'bad');
      setStatusDetail(e.detail || e.message || '');
      L.setConnected(false);
    }
  }

  function save() {
    L.saveKey(val.trim());
    L.setLiveMode(live);
    L.closeSettings();
  }

  const rl = L.rateLimit;
  const statusMap = {
    idle: { c: 'var(--text-muted)', t: 'Not tested' },
    testing: { c: 'var(--accent)', t: 'Testing…' },
    ok: { c: 'var(--up)', t: 'Connected · key valid' + (rl.remaining != null ? ' · ' + rl.remaining + '/' + rl.limit + ' req left' : '') },
    bad: { c: 'var(--down)', t: 'Invalid key or no access' },
    net: { c: 'var(--down)', t: 'Network/CORS blocked — check connection' },
  }[status];

  return (
    <div className="modal-scrim" onClick={L.closeSettings}>
      <div className="modal-sheet" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3 className="h3">Connect live data</h3>
          <button className="icon-btn" onClick={L.closeSettings}><Icon name="x" /></button>
        </div>
        <div className="modal-body">
          <p style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 0 }}>
            Company Stock Price can pull live news and global data from <strong>Finnhub</strong>.
            Keys are stored in this browser or loaded from <code>src/config/local.js</code> for local dev.
          </p>
          <label className="label-up" style={{ display: 'block', marginBottom: 6 }}>Finnhub API key</label>
          <div style={{ display: 'flex', gap: 8 }}>
            <input className="key-input" type="password" value={val} placeholder="From finnhub.io/dashboard"
              onChange={(e) => { setVal(e.target.value); setStatus('idle'); }} />
            <button className="pill" style={{ height: 42 }} onClick={test} disabled={!val.trim()}>Test</button>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginTop: 10 }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', background: statusMap.c }}></span>
            <span style={{ fontSize: 12, color: statusMap.c, fontWeight: 600 }}>
              {statusMap.t}{statusDetail ? ' — ' + statusDetail : ''}
            </span>
          </div>

          <label className="live-toggle">
            <div>
              <div style={{ fontWeight: 600, fontSize: 14 }}>Use live data</div>
              <div className="muted">News, search, IPO calendar &amp; global stock detail via Finnhub API.</div>
            </div>
            <button className={`switch ${live ? 'on' : ''}`} onClick={() => setLiveLocal((x) => !x)} aria-label="Toggle live data">
              <span className="knob"></span>
            </button>
          </label>

          <div className="modal-note">
            <Icon name="news" size={15} />
            <span>NSE quotes load automatically. Optional Finnhub key unlocks live news &amp; global US indices.</span>
          </div>
        </div>
        <div className="modal-foot">
          <button className="pill" style={{ height: 42 }} onClick={L.closeSettings}>Cancel</button>
          <button className="pill active" style={{ height: 42 }} onClick={save}>Save</button>
        </div>
      </div>
    </div>
  );
}

function LiveBadge({ live, small }) {
  return (
    <span className={`live-badge ${live ? 'on' : ''} ${small ? 'sm' : ''}`}>
      <span className="lb-dot"></span>{live ? 'LIVE' : 'DEMO'}
    </span>
  );
}

Object.assign(window, { LiveCtx, useLive, LiveProvider, SettingsModal, LiveBadge, curSym, relTime, mcapM, mapNews, buildLiveStock });
