/* ============================================================
   JTSense App — shared components & charts
   ============================================================ */
const { useState, useEffect, useRef, useMemo } = React;

/* ---- tiny icon set (stroke) ---- */
const Icon = ({ d, fill }) => (
  <svg viewBox="0 0 24 24" fill={fill ? "currentColor" : "none"} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    {Array.isArray(d) ? d.map((p, i) => <path key={i} d={p} />) : <path d={d} />}
  </svg>
);
const ICONS = {
  overview: "M3 13h8V3H3zM13 21h8V3h-8zM3 21h8v-6H3z",
  narrative: "M3 12h4l3-8 4 16 3-8h4",
  wallet: ["M3 7h18v10H3z", "M16 12h2"],
  signal: ["M4 12a8 8 0 0 1 8-8", "M4 12a8 8 0 0 0 8 8", "M12 12h.01", "M8 12a4 4 0 0 1 4-4", "M8 12a4 4 0 0 0 4 4"],
  alert: ["M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9", "M13.7 21a2 2 0 0 1-3.4 0"],
  watch: ["M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z", "M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"],
  analytics: ["M3 3v18h18", "M7 14l3-3 3 3 5-6"],
  settings: ["M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z", "M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-2.9 1.2 2 2 0 1 1-4 0 1.7 1.7 0 0 0-2.9-1.2l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.6-1H3a2 2 0 1 1 0-4h.1A1.7 1.7 0 0 0 4.6 9a1.7 1.7 0 0 0-.3-1.9l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1A1.7 1.7 0 0 0 10 4.6a1.7 1.7 0 0 0 1-1.6V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 2.9 1.2l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.6 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"],
  search: ["M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16z", "M21 21l-4.3-4.3"],
  bell: ["M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9", "M13.7 21a2 2 0 0 1-3.4 0"],
  logout: ["M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4", "M16 17l5-5-5-5", "M21 12H9"],
  up: "M7 17L17 7M17 7H8M17 7v9",
  down: "M7 7l10 10M17 17H8M17 17V8",
};

/* ---- Sparkline ---- */
function Spark({ data, color = "#4ea2ff", w = 90, h = 30, fill = true }) {
  const max = Math.max(...data), min = Math.min(...data);
  const rng = max - min || 1;
  const pts = data.map((v, i) => [(i / (data.length - 1)) * w, h - ((v - min) / rng) * (h - 4) - 2]);
  const line = pts.map((p, i) => (i ? "L" : "M") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" ");
  const area = line + ` L${w} ${h} L0 ${h} Z`;
  const gid = "sg" + useMemo(() => Math.random().toString(36).slice(2, 7), []);
  return (
    <svg width={w} height={h} style={{ display: "block" }}>
      <defs><linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stopColor={color} stopOpacity="0.35" /><stop offset="1" stopColor={color} stopOpacity="0" />
      </linearGradient></defs>
      {fill && <path d={area} fill={`url(#${gid})`} />}
      <path d={line} fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

/* ---- Bars ---- */
function Bars({ data, color = "#4ea2ff", h = 56 }) {
  const max = Math.max(...data) || 1;
  return (
    <div style={{ display: "flex", alignItems: "flex-end", gap: 3, height: h }}>
      {data.map((v, i) => (
        <div key={i} style={{
          flex: 1, height: (v / max) * 100 + "%", borderRadius: "2px 2px 0 0",
          background: `linear-gradient(180deg, ${color}, ${color}22)`,
        }} />
      ))}
    </div>
  );
}

/* ---- Line chart with two series ---- */
function LineChart({ series, w = 560, h = 180, labels }) {
  const all = series.flatMap(s => s.data);
  const max = Math.max(...all), min = Math.min(...all);
  const rng = max - min || 1;
  const pad = 8;
  const px = i => (i / (series[0].data.length - 1)) * (w - pad * 2) + pad;
  const py = v => h - pad - ((v - min) / rng) * (h - pad * 2);
  return (
    <svg width="100%" viewBox={`0 0 ${w} ${h}`} style={{ display: "block" }}>
      {[0.25, 0.5, 0.75].map((g, i) => (
        <line key={i} x1="0" x2={w} y1={h * g} y2={h * g} stroke="rgba(86,130,210,.1)" strokeWidth="1" />
      ))}
      {series.map((s, si) => {
        const line = s.data.map((v, i) => (i ? "L" : "M") + px(i).toFixed(1) + " " + py(v).toFixed(1)).join(" ");
        return <path key={si} d={line} fill="none" stroke={s.color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />;
      })}
    </svg>
  );
}

/* ---- Donut ---- */
function Donut({ value, color = "#4ea2ff", size = 110, label }) {
  const r = size / 2 - 9, c = 2 * Math.PI * r;
  return (
    <div style={{ position: "relative", width: size, height: size }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="rgba(86,130,210,.14)" strokeWidth="8" />
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={color} strokeWidth="8" strokeLinecap="round"
          strokeDasharray={c} strokeDashoffset={c * (1 - value / 100)} style={{ transition: "stroke-dashoffset 1s ease" }} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
        <div>
          <div style={{ fontFamily: "var(--f-display)", fontWeight: 700, fontSize: 22 }}>{value}%</div>
          {label && <div style={{ fontFamily: "var(--f-mono)", fontSize: 10, color: "var(--tx-mute)" }}>{label}</div>}
        </div>
      </div>
    </div>
  );
}

/* ---- Card wrapper ---- */
function Card({ title, more, onMore, children, style }) {
  return (
    <div className="card" style={style}>
      {(title || more) && (
        <div className="card-h">
          {title && <h3>{title}</h3>}
          {more && <span className="more" onClick={onMore}>{more}</span>}
        </div>
      )}
      {children}
    </div>
  );
}

/* ---- Type chip ---- */
function TypeChip({ type }) {
  const cls = { NARRATIVE: "tag-narrative", WHALE: "tag-whale", FLOW: "tag-flow", TOKEN: "tag-token", RISK: "tag-risk" }[type];
  return <span className={"chip " + cls} style={{ fontSize: 10 }}>{type}</span>;
}

Object.assign(window, { Icon, ICONS, Spark, Bars, LineChart, Donut, Card, TypeChip });
