/* ============================================================
   JTSense App — views: Overview · Narratives · Wallets
   ============================================================ */

/* ---- squarified treemap layout ---- */
function squarify(items, W, H) {
  const out = [];
  const total = items.reduce((a, b) => a + b.value, 0) || 1;
  const data = items.map(it => ({ it, area: it.value / total * (W * H) }));
  let rx = 0, ry = 0, rw = W, rh = H, row = [];
  const worst = (r, len) => {
    const s = r.reduce((a, b) => a + b.area, 0);
    const mx = Math.max(...r.map(b => b.area)), mn = Math.min(...r.map(b => b.area));
    return Math.max((len * len * mx) / (s * s), (s * s) / (len * len * mn));
  };
  const layout = (r) => {
    const s = r.reduce((a, b) => a + b.area, 0);
    if (rw >= rh) {
      const cw = s / rh; let yy = ry;
      r.forEach(b => { const bh = b.area / cw; out.push({ ...b.it, rx, ry: yy, rw: cw, rh: bh }); yy += bh; });
      rx += cw; rw -= cw;
    } else {
      const ch = s / rw; let xx = rx;
      r.forEach(b => { const bw = b.area / ch; out.push({ ...b.it, rx: xx, ry, rw: bw, rh: ch }); xx += bw; });
      ry += ch; rh -= ch;
    }
  };
  while (data.length) {
    const c = data[0], len = Math.min(rw, rh);
    if (row.length === 0 || worst(row, len) >= worst(row.concat(c), len)) { row.push(c); data.shift(); }
    else { layout(row); row = []; }
  }
  if (row.length) layout(row);
  return out;
}
function heatColor(t) {
  const stops = [[16, 34, 64], [31, 95, 192], [74, 196, 255]];
  const [a, b, f] = t < 0.5 ? [stops[0], stops[1], t * 2] : [stops[1], stops[2], (t - 0.5) * 2];
  const c = a.map((v, i) => Math.round(v + (b[i] - v) * f));
  return `rgb(${c[0]},${c[1]},${c[2]})`;
}
function NarrativeHeatmap({ tick, go }) {
  const J = window.JT;
  const ref = useRef(null);
  const [w, setW] = useState(380);
  useEffect(() => {
    if (!ref.current) return;
    const ro = new ResizeObserver(es => { for (const e of es) setW(e.contentRect.width); });
    ro.observe(ref.current);
    return () => ro.disconnect();
  }, []);
  const H = 290;
  const items = [...J.narratives].sort((a, b) => b.momentum - a.momentum).slice(0, 8)
    .map(n => ({ ...n, value: Math.pow(n.momentum, 1.25) }));
  const mn = Math.min(...items.map(i => i.momentum)), mx = Math.max(...items.map(i => i.momentum));
  const tiles = squarify(items, w, H);
  return (
    <div>
      <div ref={ref} style={{ position: "relative", width: "100%", height: H }}>
        {tiles.map(t => {
          const tt = (t.momentum - mn) / ((mx - mn) || 1);
          return (
            <div key={t.name} title={`${t.name} · momentum ${t.momentum}`} onClick={() => go && go("narratives")}
              style={{
                position: "absolute", left: t.rx + 3, top: t.ry + 3,
                width: Math.max(0, t.rw - 6), height: Math.max(0, t.rh - 6),
                borderRadius: 9, background: heatColor(tt), border: "1px solid rgba(255,255,255,.1)",
                boxShadow: "inset 0 1px 0 rgba(255,255,255,.14)", overflow: "hidden", cursor: "pointer",
                transition: "background .6s ease, left .55s cubic-bezier(.22,1,.36,1), top .55s cubic-bezier(.22,1,.36,1), width .55s cubic-bezier(.22,1,.36,1), height .55s cubic-bezier(.22,1,.36,1)",
                padding: "9px 11px", display: "flex", flexDirection: "column", justifyContent: "space-between",
              }}>
              <div style={{ fontFamily: "var(--f-display)", fontWeight: 600, fontSize: t.rw < 78 ? 11 : 14, color: "#fff", lineHeight: 1.12, textShadow: "0 1px 4px rgba(0,0,0,.45)" }}>{t.name}</div>
              {t.rh > 44 && t.rw > 56 && (
                <div style={{ fontFamily: "var(--f-mono)", fontSize: 11, color: "rgba(255,255,255,.9)", textShadow: "0 1px 3px rgba(0,0,0,.5)" }}>
                  {t.momentum}<span style={{ opacity: .65 }}> · {t.eco}</span>
                </div>
              )}
            </div>
          );
        })}
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 9, marginTop: 13, fontFamily: "var(--f-mono)", fontSize: 10, color: "var(--tx-mute)" }}>
        <span>Low momentum</span>
        <div style={{ flex: 1, height: 6, borderRadius: 3, background: "linear-gradient(90deg,#102240,#1f5fc0,#4ac4ff)" }} />
        <span>High</span>
      </div>
    </div>
  );
}

/* ---------------- OVERVIEW ---------------- */
function OverviewView({ signals, go, tick }) {
  const J = window.JT;
  const k = J.kpis;
  const recent = signals.slice(0, 6);
  return (
    <div className="grid" style={{ gridTemplateColumns: "1fr" }}>
      <div className="grid kpi-row">
        <Kpi lab="Total Signals" val={k.totalSignals.toLocaleString()} chg="+24.5%" up data={J.kpiSpark.signals} />
        <Kpi lab="AI Confidence" val={k.aiConfidence + "%"} chg="High" color="var(--blue-bright)" data={J.kpiSpark.confidence} />
        <Kpi lab="Hot Narratives" val={k.hotNarratives} chg="+5" up data={J.kpiSpark.narratives} />
        <Kpi lab="Smart Wallets" val={k.smartWallets.toLocaleString()} chg="+18.7%" up data={J.kpiSpark.wallets} />
      </div>

      <div className="grid" style={{ gridTemplateColumns: "1.3fr 1fr" }}>
        <Card title="Realtime Signals" more="View all →" onMore={() => go("signals")}>
          <div className="sigfeed">
            {recent.map(s => (
              <div className="sigrow" key={s.id}>
                <TypeChip type={s.type} />
                <span className="lbl">{s.label}</span>
                <span className="cf" style={{ color: J.typeColor[s.type] }}>{s.confidence}%</span>
                <span className="tm">{J.fmt.ago(s.ts)}</span>
              </div>
            ))}
          </div>
        </Card>

        <Card title="Narrative Heatmap" more="Narratives →" onMore={() => go("narratives")}>
          <NarrativeHeatmap tick={tick} go={go} />
        </Card>
      </div>

      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr" }}>
        <Card title="Smart Wallet Flow · 24h" more="Wallets →" onMore={() => go("wallets")}>
          <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", gap: 14 }}>
            <div>
              <div style={{ fontFamily: "var(--f-mono)", fontSize: 11, color: "var(--tx-mute)" }}>NET INFLOW</div>
              <div style={{ fontFamily: "var(--f-display)", fontWeight: 700, fontSize: 26, color: J.live.netInflow >= 0 ? "var(--up)" : "var(--down)" }}>{J.fmt.money(J.live.netInflow)}</div>
              <div style={{ display: "flex", gap: 14, marginTop: 10, fontFamily: "var(--f-mono)", fontSize: 11 }}>
                <span style={{ color: "var(--up)" }}>● Inflow</span>
                <span style={{ color: "var(--purple)" }}>● Outflow</span>
              </div>
            </div>
            <div style={{ flex: 1, maxWidth: 280 }}>
              <LineChart w={300} h={110} series={[
                { color: "#27d98a", data: J.kpiSpark.wallets.slice(-12) },
                { color: "#a855f7", data: J.kpiSpark.wallets.slice(-12).map(v => Math.max(8, 92 - v)) },
              ]} />
            </div>
          </div>
        </Card>

        <Card title="Market Sentiment" more="Analytics →" onMore={() => go("analytics")}>
          <div style={{ display: "flex", gap: 18, alignItems: "center" }}>
            <Donut value={J.live.sentBull} color="#27d98a" label="Bullish" />
            <div style={{ flex: 1 }}>
              <SentRow lab="Bullish" val={J.live.sentBull} color="#27d98a" />
              <SentRow lab="Bearish" val={100 - J.live.sentBull} color="#ff5b7a" />
              <div style={{ marginTop: 12 }}>
                <LineChart w={260} h={70} series={[
                  { color: "#27d98a", data: window.JT.sentiment.map(s => s.bull) },
                  { color: "#ff5b7a", data: window.JT.sentiment.map(s => s.bear) },
                ]} />
              </div>
            </div>
          </div>
        </Card>
      </div>
    </div>
  );
}

function Kpi({ lab, val, chg, up, color, data }) {
  return (
    <div className="kpi">
      <div className="lab">{lab}</div>
      <div className="val" style={color ? { color } : {}}>{val}</div>
      <div className="chg" style={{ color: up ? "var(--up)" : (color || "var(--tx-mute)") }}>
        {up && "▲ "}{chg}
      </div>
      <div style={{ marginTop: 10 }}><Spark data={data} color={color && color.includes("blue") ? "#4ea2ff" : (up ? "#27d98a" : "#4ea2ff")} w={150} h={34} /></div>
    </div>
  );
}
function SentRow({ lab, val, color }) {
  return (
    <div style={{ marginBottom: 8 }}>
      <div style={{ display: "flex", justifyContent: "space-between", fontFamily: "var(--f-mono)", fontSize: 12, marginBottom: 4 }}>
        <span style={{ color: "var(--tx-soft)" }}>{lab}</span><span style={{ color }}>{val}%</span>
      </div>
      <div style={{ height: 6, borderRadius: 3, background: "var(--panel-3)", overflow: "hidden" }}>
        <div style={{ width: val + "%", height: "100%", background: color, borderRadius: 3 }} />
      </div>
    </div>
  );
}

/* ---------------- NARRATIVES ---------------- */
function NarrativesView({ isWatched, toggleWatch, tick }) {
  const J = window.JT;
  const [sort, setSort] = useState({ key: "momentum", dir: -1 });
  const rows = useMemo(() => {
    const r = [...J.narratives];
    r.sort((a, b) => (a[sort.key] > b[sort.key] ? 1 : -1) * sort.dir);
    return r;
  }, [sort, tick]);
  const setS = key => setSort(s => ({ key, dir: s.key === key ? -s.dir : -1 }));
  return (
    <div className="grid" style={{ gridTemplateColumns: "1fr" }}>
      <div className="grid" style={{ gridTemplateColumns: "repeat(3,1fr)" }}>
        <MiniStat lab="Tracked Narratives" val={J.kpis.hotNarratives} sub="+5 today" />
        <MiniStat lab="Avg Velocity" val={(J.narratives.reduce((a,n)=>a+n.velocity,0)/J.narratives.length).toFixed(2)} sub="social momentum" color="var(--blue-bright)" />
        <MiniStat lab="Top Mover" val={[...J.narratives].sort((a,b)=>b.change-a.change)[0].name} sub={"+"+[...J.narratives].sort((a,b)=>b.change-a.change)[0].change+"% · 24h"} color="var(--down)" />
      </div>
      <Card title="Narrative Intelligence">
        <table className="tbl">
          <thead><tr>
            <th onClick={() => setS("name")}>Narrative</th>
            <th onClick={() => setS("eco")}>Ecosystem</th>
            <th onClick={() => setS("momentum")}>Momentum</th>
            <th onClick={() => setS("velocity")}>Velocity</th>
            <th onClick={() => setS("change")}>24h</th>
            <th onClick={() => setS("mentions")}>Mentions</th>
            <th>Trend</th>
            <th></th>
          </tr></thead>
          <tbody>
            {rows.map(n => {
              const key = "narr:" + n.name;
              return (
                <tr key={n.name}>
                  <td><b style={{ color: "var(--tx)" }}>{n.name}</b></td>
                  <td><span className="chip" style={{ fontSize: 10 }}>{n.eco}</span></td>
                  <td>
                    <span className="score-bar"><i style={{ width: n.momentum + "%" }} /></span>
                    <span style={{ marginLeft: 8, fontFamily: "var(--f-mono)", fontSize: 12 }}>{n.momentum}</span>
                  </td>
                  <td className="mono" style={{ color: "var(--blue-bright)" }}>{n.velocity.toFixed(2)}</td>
                  <td className={n.change >= 0 ? "up mono" : "down mono"}>{n.change >= 0 ? "+" : ""}{n.change}%</td>
                  <td className="mono">{n.mentions.toLocaleString()}</td>
                  <td><Spark data={[6,7,5,8,7,9,8,n.momentum/10]} color={n.color} w={70} h={26} fill={false} /></td>
                  <td><span className={"star " + (isWatched(key) ? "on" : "")} onClick={() => toggleWatch({ key, kind: "Narrative", label: n.name })}>{isWatched(key) ? "★" : "☆"}</span></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </Card>
    </div>
  );
}

function MiniStat({ lab, val, sub, color }) {
  return (
    <div className="card">
      <div className="lab" style={{ fontFamily: "var(--f-mono)", fontSize: 11, letterSpacing: ".08em", textTransform: "uppercase", color: "var(--tx-mute)" }}>{lab}</div>
      <div style={{ fontFamily: "var(--f-display)", fontWeight: 700, fontSize: 28, marginTop: 6, color: color || "var(--tx)" }}>{val}</div>
      <div style={{ fontFamily: "var(--f-mono)", fontSize: 12, color: "var(--tx-mute)", marginTop: 4 }}>{sub}</div>
    </div>
  );
}

/* ---------------- WALLETS ---------------- */
function WalletsView({ isWatched, toggleWatch, tick }) {
  const J = window.JT;
  const [sel, setSel] = useState(null);
  const [sort, setSort] = useState({ key: "score", dir: -1 });
  const rows = useMemo(() => {
    const r = [...J.wallets];
    r.sort((a, b) => (a[sort.key] > b[sort.key] ? 1 : -1) * sort.dir);
    return r;
  }, [sort, tick]);
  const setS = key => setSort(s => ({ key, dir: s.key === key ? -s.dir : -1 }));
  return (
    <div className="grid" style={{ gridTemplateColumns: "1fr" }}>
      <div className="grid" style={{ gridTemplateColumns: "repeat(3,1fr)" }}>
        <MiniStat lab="Smart Wallets Tracked" val={J.kpis.smartWallets.toLocaleString()} sub="+18.7% this week" />
        <MiniStat lab="Net Inflow · 24h" val={J.fmt.money(J.live.netInflow)} sub="across tracked set" color={J.live.netInflow>=0?"var(--up)":"var(--down)"} />
        <MiniStat lab="Avg Smart Score" val={Math.round(J.wallets.reduce((a,w)=>a+w.score,0)/J.wallets.length)} sub="of top 14 shown" color="var(--blue-bright)" />
      </div>
      <Card title="Wallet Intelligence">
        <table className="tbl">
          <thead><tr>
            <th onClick={() => setS("address")}>Address</th>
            <th onClick={() => setS("label")}>Label</th>
            <th onClick={() => setS("score")}>Smart Score</th>
            <th onClick={() => setS("flow")}>Flow · 24h</th>
            <th onClick={() => setS("win")}>Win Rate</th>
            <th>Holdings</th>
            <th></th>
          </tr></thead>
          <tbody>
            {rows.map(w => {
              const key = "wal:" + w.address + w.id;
              return (
                <tr key={w.id} onClick={() => setSel(w)}>
                  <td className="addr">{w.address}</td>
                  <td><span className="chip" style={{ fontSize: 10 }}>{w.label}</span></td>
                  <td>
                    <span className="score-bar"><i style={{ width: w.score + "%" }} /></span>
                    <span style={{ marginLeft: 8, fontFamily: "var(--f-mono)", fontSize: 12 }}>{w.score}</span>
                  </td>
                  <td className={w.flow >= 0 ? "up mono" : "down mono"}>{J.fmt.money(w.flow)}</td>
                  <td className="mono">{w.win}%</td>
                  <td className="mono" style={{ fontSize: 12, color: "var(--tx-mute)" }}>{w.tokens.join(" · ")}</td>
                  <td onClick={e => e.stopPropagation()}>
                    <span className={"star " + (isWatched(key) ? "on" : "")} onClick={() => toggleWatch({ key, kind: "Wallet", label: w.address })}>{isWatched(key) ? "★" : "☆"}</span>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </Card>
      {sel && <WalletDrawer w={sel} onClose={() => setSel(null)} isWatched={isWatched} toggleWatch={toggleWatch} />}
    </div>
  );
}

function WalletDrawer({ w, onClose, isWatched, toggleWatch }) {
  const J = window.JT;
  const key = "wal:" + w.address + w.id;
  const flowHist = Array.from({ length: 16 }).map(() => J.rnd(-3, 6));
  return (
    <React.Fragment>
      <div className="drawer-mask" onClick={onClose} />
      <div className="drawer">
        <span className="x" onClick={onClose}>✕</span>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <div className="avatar" style={{ width: 44, height: 44, fontSize: 16 }}>{w.label[0]}</div>
          <div>
            <div className="addr" style={{ fontSize: 16 }}>{w.address}</div>
            <span className="chip" style={{ fontSize: 10, marginTop: 5, display: "inline-block" }}>{w.label}</span>
          </div>
        </div>
        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", marginTop: 22 }}>
          <DrawerStat lab="Smart Score" val={w.score} color="var(--blue-bright)" />
          <DrawerStat lab="Win Rate" val={w.win + "%"} />
          <DrawerStat lab="Flow · 24h" val={J.fmt.money(w.flow)} color={w.flow >= 0 ? "var(--up)" : "var(--down)"} />
          <DrawerStat lab="Transactions" val={w.txns} />
        </div>
        <div style={{ marginTop: 22 }}>
          <div className="lab" style={{ fontFamily: "var(--f-mono)", fontSize: 11, color: "var(--tx-mute)", marginBottom: 10 }}>FLOW HISTORY · 16D</div>
          <Bars data={flowHist.map(v => v + 4)} color="#4ea2ff" h={70} />
        </div>
        <div style={{ marginTop: 22 }}>
          <div className="lab" style={{ fontFamily: "var(--f-mono)", fontSize: 11, color: "var(--tx-mute)", marginBottom: 10 }}>TOP HOLDINGS</div>
          {w.tokens.map((t, i) => (
            <div key={i} style={{ display: "flex", justifyContent: "space-between", padding: "9px 0", borderBottom: "1px solid var(--line)", fontFamily: "var(--f-mono)", fontSize: 13 }}>
              <span style={{ color: "var(--tx)" }}>{t}</span>
              <span style={{ color: "var(--tx-mute)" }}>{Math.round(J.rnd(8, 42))}%</span>
            </div>
          ))}
        </div>
        <button className={"btn " + (isWatched(key) ? "btn-ghost" : "btn-primary")} style={{ width: "100%", marginTop: 24 }}
          onClick={() => toggleWatch({ key, kind: "Wallet", label: w.address })}>
          {isWatched(key) ? "★ Remove from Watchlist" : "☆ Add to Watchlist"}
        </button>
      </div>
    </React.Fragment>
  );
}
function DrawerStat({ lab, val, color }) {
  return (
    <div style={{ background: "var(--panel-3)", border: "1px solid var(--line)", borderRadius: 10, padding: 14 }}>
      <div style={{ fontFamily: "var(--f-mono)", fontSize: 10, letterSpacing: ".08em", textTransform: "uppercase", color: "var(--tx-mute)" }}>{lab}</div>
      <div style={{ fontFamily: "var(--f-display)", fontWeight: 700, fontSize: 22, marginTop: 6, color: color || "var(--tx)" }}>{val}</div>
    </div>
  );
}

Object.assign(window, { OverviewView, NarrativesView, WalletsView });
