/* ===== ArbitrajZ — Dashboard app ===== */

/* ---- tiny helpers ---- */
function pad(n) { return n < 10 ? "0" + n : "" + n; }
function fmtClock(d) { return pad(d.getHours()) + ":" + pad(d.getMinutes()); }
function StabilityMeter({ level }) {
  // High = 3 bars, Med = 2, Low = 1
  const n = level === "High" ? 3 : level === "Med" ? 2 : 1;
  return (
    <span className="stab-meter" aria-hidden="true">
      {[0, 1, 2].map((i) => (
        <i key={i} className={i < n ? "on" : ""} />
      ))}
    </span>
  );
}

/* ---- info tooltip ---- */
function InfoTip({ text }) {
  const [pos, setPos] = useState(null);
  const ref = useRef(null);

  function show() {
    if (!ref.current) return;
    const r = ref.current.getBoundingClientRect();
    setPos({ top: r.bottom + 7, left: r.left + r.width / 2 });
  }

  return (
    <span className="infotip"
      onMouseEnter={show}
      onMouseLeave={() => setPos(null)}
      onClick={(e) => { e.stopPropagation(); pos ? setPos(null) : show(); }}>
      <span ref={ref} className="infotip-icon" aria-label="info">i</span>
      {pos && (
        <span className="infotip-bubble" role="tooltip"
          style={{ top: pos.top + "px", left: pos.left + "px" }}>
          {text}
        </span>
      )}
    </span>
  );
}

/* ---- top bar ---- */
function TopBar({ scanning, exchanges }) {
  const NAV = [
    { label: "Dashboard", href: "/" },
    { label: "Opportunities", href: "/opportunities.html" },
    { label: "Alerts" },
    { label: "Help", href: "/help.html" },
  ];
  const [active, setActive] = useState("Dashboard");
  const lastScanRaw = window.ARBZ.SUMMARY.lastScan;
  const scanDisplay = lastScanRaw ? fmtClock(new Date(lastScanRaw)) : "--:--";
  return (
    <header className="topbar">
      <div className="topbar-inner">
        <a className="brand" href="/">
          <ChartMark size={32} />
          <span className="wordmark">Arbitraj<span className="wm-z">Z</span></span>
        </a>
        <nav className="nav">
          {NAV.map(({ label, href }) =>
            href
              ? <a key={label} href={href} className="nav-link">{label}</a>
              : <button key={label}
                  className={"nav-link" + (active === label ? " is-active" : "")}
                  onClick={() => setActive(label)}>
                  {label}
                </button>
          )}
        </nav>
        <div className={"status-pill" + (scanning ? " scanning" : "")}>
          <span className="live-dot"><i /></span>
          <span className="status-text">
            <b>Live</b>
            <span className="sep">·</span>
            <span className="muted">last scan</span>&nbsp;
            <span className="mono">{scanning ? "scanning…" : scanDisplay}</span>
            <span className="sep">·</span>
            <span className="mono">{exchanges}</span>&nbsp;<span className="muted">exchanges</span>
          </span>
        </div>
      </div>
    </header>
  );
}

/* ---- summary metric cards ---- */
function MetricCard({ label, children, accent, sub, tip }) {
  return (
    <div className={"metric" + (accent ? " metric--accent" : "")}>
      <div className="metric-label">{label}{tip && <InfoTip text={tip} />}</div>
      <div className="metric-value">{children}</div>
      {sub && <div className="metric-sub">{sub}</div>}
    </div>
  );
}

function Summary({ s }) {
  return (
    <section className="summary">
      <MetricCard label="Clean signals now" sub="passed stability + safety" tip="Signals that passed our stability and safety filters right now.">
        <span className="mono">{s.cleanSignalsTotal}</span>
      </MetricCard>
      <MetricCard label="Best net APR · 7d" accent sub="after est. fees & funding" tip="Annualized funding yield over 7 days, after estimated fees.">
        <span className="mono pos">{s.bestApr.toFixed(1)}%</span>
      </MetricCard>
      <MetricCard label="Pairs scanned" sub="perp + spot, 4 venues" tip="Total perp+spot pairs checked across all exchanges each scan.">
        <span className="mono">{s.pairsScanned.toLocaleString()}</span>
      </MetricCard>
      <MetricCard label="Avg stability" sub="weighted by net APR" tip="How flat the funding has been. High = consistent positive funding, low volatility.">
        <span className="stab-value">High <StabilityMeter level="High" /></span>
      </MetricCard>
    </section>
  );
}

/* ---- one opportunity ---- */
function OppRow({ o, open, onToggle }) {
  const stable = o.stable;
  const exLeg = `${o.base}\u2011PERP`;
  return (
    <div className={"opp" + (open ? " is-open" : "")}>
      <button className="opp-main" onClick={onToggle} aria-expanded={open}>
        {/* pair */}
        <div className="opp-pair">
          <div className="opp-pair-top">
            <span className="opp-sym">{o.base} <span className="slash">/</span> {o.quote}</span>
            <span className="ex-badge">{o.exchange}</span>
          </div>
          <div className="opp-strategy">
            <span className="dn-dot" /> delta-neutral · spot + perp short<InfoTip text="Long spot + short perp in equal size. Price moves cancel out; you only collect funding." />
          </div>
        </div>

        {/* net APR */}
        <div className="opp-apr">
          <div className="apr-val mono pos">+{o.netApr.toFixed(1)}%</div>
          <div className="apr-cap">net APR · 7d<InfoTip text="Annualized yield from funding payments over the last 7 days, after estimated fees." /></div>
        </div>

        {/* sparkline — hero */}
        <div className="opp-spark">
          <Sparkline series={o.series} stable={stable} />
          <div className="spark-cap">
            7d funding —{" "}
            <span className={stable ? "cap-good" : "cap-warn"}>
              {stable ? "flat, stays positive" : "choppy, dips negative"}
            </span>
          </div>
        </div>

        {/* risk badge */}
        <div className="opp-risk">
          <span className={"badge " + (stable ? "badge--ok" : "badge--warn")}>
            <span className="badge-dot" />
            {stable ? "stable" : "volatile"}
            <span className="badge-neg">· {o.negCount} neg<InfoTip text="How many times funding went negative in 7 days. 0 = you earned every interval; more = you paid on those intervals." /></span>
          </span>
          <div className="risk-cap">7-day funding flips</div>
        </div>

        {/* secondary stats */}
        <div className="opp-stats">
          <div><span className="st-k">breakeven<InfoTip text="Hours you must hold for funding income to cover entry + exit fees." /></span> <span className="mono st-v">{o.breakevenH}h</span></div>
          <div><span className="st-k">24h vol</span> <span className="mono st-v">${o.volM}M</span></div>
        </div>

        <span className="chev" aria-hidden="true">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2">
            <path d="M6 9l6 6 6-6" />
          </svg>
        </span>
      </button>

      {open && <OppDetail o={o} exLeg={exLeg} />}
    </div>
  );
}

function OppDetail({ o, exLeg }) {
  const avg = o.series.reduce((a, b) => a + b, 0) / o.series.length;
  const stable = o.stable;
  return (
    <div className="opp-detail">
      <div className="legs">
        <div className="leg">
          <span className="leg-tag long">LONG</span>
          <div>
            <div className="leg-name mono">{o.base}/{o.quote} <span className="muted">spot</span></div>
            <div className="leg-sub">{o.exchange} · collects nothing, hedges price</div>
          </div>
        </div>
        <span className="leg-link">delta-neutral</span>
        <div className="leg">
          <span className="leg-tag short">SHORT</span>
          <div>
            <div className="leg-name mono">{exLeg} <span className="muted">perp</span></div>
            <div className="leg-sub">{o.exchange} · earns funding every 8h</div>
          </div>
        </div>
      </div>

      <div className="detail-stats">
        <Stat k="Current funding" v={(o.curFunding >= 0 ? "+" : "") + o.curFunding.toFixed(4) + "%"} tone={o.curFunding >= 0 ? "pos" : "neg"} sub="per 8h" />
        <Stat k="7d avg funding" v={(avg >= 0 ? "+" : "") + avg.toFixed(4) + "%"} tone="pos" sub="per 8h" />
        <Stat k="Negative events" v={o.negCount} tone={stable ? "pos" : "warn"} sub="in last 7d" />
        <Stat k="Est. net APR" v={"+" + o.netApr.toFixed(1) + "%"} tone="pos" sub="after fees" />
        <Stat k="Breakeven" v={o.breakevenH + "h"} sub="to clear costs" />
        <Stat k="24h volume" v={"$" + o.volM + "M"} sub="thinner = slower fills" />
      </div>

      <div className={"detail-note " + (stable ? "note-ok" : "note-warn")}>
        <span className="note-ic">{stable ? "✓" : "!"}</span>
        {stable
          ? `Funding held positive across all 21 intervals this week. Carry has been steady — this is the kind of clean, boring signal we surface first.`
          : `Headline APR looks comparable, but funding flipped negative ${o.negCount}× this week. Each flip means you paid instead of earned. Size down or skip — the 7d average can hide a bumpy ride.`}
      </div>

      <div className="detail-actions">
        <ActionBtn primary>Set funding alert</ActionBtn>
        <ActionBtn onAction={() => window.open(pairUrl(o), "_blank")}>Open pair</ActionBtn>
        <span className="updated mono">refreshed just now</span>
      </div>
    </div>
  );
}

function pairUrl(o) {
  const base = (o.base || "").toUpperCase();
  const ex = (o.exchange || "").toLowerCase();
  if (ex === "bybit")   return "https://www.bybit.com/trade/usdt/" + base + "USDT";
  if (ex === "binance") return "https://www.binance.com/en/futures/" + base + "USDT";
  if (ex === "okx")     return "https://www.okx.com/trade-swap/" + base.toLowerCase() + "-usdt-swap";
  if (ex === "gate")    return "https://www.gate.io/futures/USDT/" + base + "_USDT";
  return "https://www.google.com/search?q=" + encodeURIComponent(base + " USDT perpetual " + (o.exchange || ""));
}

function Stat({ k, v, sub, tone }) {
  return (
    <div className="dstat">
      <div className="dstat-k">{k}</div>
      <div className={"dstat-v mono " + (tone || "")}>{v}</div>
      {sub && <div className="dstat-sub">{sub}</div>}
    </div>
  );
}

function ActionBtn({ children, primary, onAction }) {
  const [hit, setHit] = useState(false);
  return (
    <button
      className={"act-btn" + (primary ? " act-btn--primary" : "") + (hit ? " is-hit" : "")}
      onClick={() => { setHit(true); if (onAction) onAction(); setTimeout(() => setHit(false), 1100); }}>
      {hit ? (primary ? "Alert set ✓" : "Opening…") : children}
    </button>
  );
}

/* ---- opportunities section ---- */
function Opportunities({ opps }) {
  const [sort, setSort] = useState("stability");
  const [stableOnly, setStableOnly] = useState(false);
  const [openId, setOpenId] = useState("apex");
  const [refreshIn, setRefreshIn] = useState(60);

  useEffect(() => {
    const t = setInterval(() => setRefreshIn((r) => (r <= 1 ? 60 : r - 1)), 1000);
    return () => clearInterval(t);
  }, []);

  const list = useMemo(() => {
    let xs = opps.slice();
    if (stableOnly) xs = xs.filter((o) => o.stable);
    if (sort === "stability") xs.sort((a, b) => a.negCount - b.negCount || b.netApr - a.netApr);
    else xs.sort((a, b) => b.netApr - a.netApr);
    return xs;
  }, [opps, sort, stableOnly]);

  return (
    <section className="opps">
      <div className="opps-head">
        <div className="opps-title">
          <h2>Opportunities</h2>
          <span className="opps-count mono">{list.length} live</span>
        </div>
        <div className="opps-controls">
          <button
            className={"toggle" + (stableOnly ? " is-on" : "")}
            onClick={() => setStableOnly((v) => !v)}>
            <span className="toggle-track"><span className="toggle-thumb" /></span>
            Stable only
          </button>
          <div className="seg">
            <span className="seg-label">Sort</span>
            <button className={sort === "stability" ? "is-on" : ""} onClick={() => setSort("stability")}>Stability</button>
            <button className={sort === "apr" ? "is-on" : ""} onClick={() => setSort("apr")}>Net APR</button>
          </div>
        </div>
      </div>

      <div className="opps-meta mono">
        sorted by {sort === "stability" ? "stability" : "net APR"} · auto-refresh in {refreshIn}s
      </div>

      <div className="opps-list">
        {list.map((o) => (
          <OppRow key={o.id} o={o} open={openId === o.id}
            onToggle={() => setOpenId((id) => (id === o.id ? null : o.id))} />
        ))}
        {list.length === 0 && (
          <div className="opps-empty mono">No stable signals match the filter right now.</div>
        )}
      </div>
    </section>
  );
}

/* ---- root ---- */
function App() {
  const { OPPS, SUMMARY } = window.ARBZ;
  const [scanning, setScanning] = useState(false);

  // periodic "re-scan" pulse — feels alive without being noisy
  useEffect(() => {
    const t = setInterval(() => {
      setScanning(true);
      setTimeout(() => { setScanning(false); }, 1500);
    }, 18000);
    return () => clearInterval(t);
  }, []);

  return (
    <div className="page">
      <TopBar scanning={scanning} exchanges={SUMMARY.exchanges} />
      <main className="wrap">
        <Summary s={SUMMARY} />
        <Opportunities opps={OPPS} />
        <footer className="foot">
          <div className="foot-disc mono">
            Informational signals only. Not financial advice. DYOR.
          </div>
          <div className="foot-meta mono">ArbitrajZ · funding-rate arbitrage radar</div>
        </footer>
      </main>
    </div>
  );
}

/* Re-randare la fiecare refresh de date din data.js (fetch async) */
const __arbzRoot = ReactDOM.createRoot(document.getElementById("root"));
window.__ARBZ_RENDER = function () { __arbzRoot.render(<App />); };
window.__ARBZ_RENDER();
