// Mini mock UI components: verdict ring, sparklines, equity curve, heatmaps, trade rows
const { useEffect, useRef, useState, useMemo } = React;

// Animated number roll
function TickerNum({ value, prefix = "", suffix = "", decimals = 0, duration = 1200 }) {
  const [n, setN] = useState(0);
  const ref = useRef(null);
  useEffect(() => {
    let started = false;
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting && !started) {
          started = true;
          const start = performance.now();
          const tick = (t) => {
            const p = Math.min(1, (t - start) / duration);
            const eased = 1 - Math.pow(1 - p, 3);
            setN(value * eased);
            if (p < 1) requestAnimationFrame(tick);
          };
          requestAnimationFrame(tick);
        }
      });
    }, { threshold: 0.3 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, [value, duration]);
  return <span ref={ref} className="mono">{prefix}{n.toFixed(decimals)}{suffix}</span>;
}

// Sparkline
function Spark({ points, color = "#26D9B3", fill = true, h = 36, w = 140 }) {
  const min = Math.min(...points), max = Math.max(...points);
  const range = max - min || 1;
  const step = w / (points.length - 1);
  const coords = points.map((p, i) => [i * step, h - ((p - min) / range) * (h - 4) - 2]);
  const path = coords.map((c, i) => (i ? "L" : "M") + c[0].toFixed(1) + " " + c[1].toFixed(1)).join(" ");
  const areaPath = path + ` L ${w} ${h} L 0 ${h} Z`;
  const gid = "sg-" + color.replace(/[^a-z0-9]/gi,"");
  return (
    <svg className="spark" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <defs>
        <linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.35"/>
          <stop offset="100%" stopColor={color} stopOpacity="0"/>
        </linearGradient>
      </defs>
      {fill && <path d={areaPath} fill={`url(#${gid})`}/>}
      <path d={path} fill="none" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

// Verdict ring (like the OPUS reference): 3 arcs (edge magenta, stability teal, drawdown amber)
function VerdictRing({ score = 87, size = 220, animate = true }) {
  const [s, setS] = useState(animate ? 0 : score);
  const ref = useRef(null);
  useEffect(() => {
    if (!animate) return;
    let started = false;
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting && !started) {
          started = true;
          const start = performance.now(); const dur = 1600;
          const tick = (t) => {
            const p = Math.min(1, (t - start) / dur);
            const eased = 1 - Math.pow(1 - p, 3);
            setS(score * eased);
            if (p < 1) requestAnimationFrame(tick);
          };
          requestAnimationFrame(tick);
        }
      });
    }, { threshold: 0.4 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, [score, animate]);
  const cx = size/2, cy = size/2;
  const arc = (r, color, pct, off = 0) => {
    const C = 2 * Math.PI * r;
    return {
      r, stroke: color,
      dash: `${(pct/100) * C} ${C}`,
      offset: -off/100 * C,
    };
  };
  const a1 = arc(size/2 - 10, "#C13CFF", 92);  // edge
  const a2 = arc(size/2 - 28, "#FFB547", 64);  // stability/drawdown
  const a3 = arc(size/2 - 46, "#26D9B3", 99);  // avg
  return (
    <div ref={ref} className="ring" style={{width:size,height:size}}>
      <svg width={size} height={size} style={{filter:"drop-shadow(0 0 20px rgba(38,217,179,.25))"}}>
        <defs>
          <filter id="glow1"><feGaussianBlur stdDeviation="2.5"/></filter>
        </defs>
        {[a1,a2,a3].map((a,i)=>(
          <g key={i}>
            <circle cx={cx} cy={cy} r={a.r} fill="none" stroke="rgba(255,255,255,.04)" strokeWidth="5"/>
            <circle cx={cx} cy={cy} r={a.r} fill="none"
              stroke={a.stroke} strokeWidth="5" strokeLinecap="round"
              strokeDasharray={a.dash} strokeDashoffset={a.offset}
              transform={`rotate(-90 ${cx} ${cy})`} style={{filter:"url(#glow1)"}}/>
          </g>
        ))}
      </svg>
      <div className="ring-num">
        <div className="n g-text">{Math.round(s)} <span style={{color:"var(--tm)",fontSize:"22px",fontWeight:500}}>/ 100</span></div>
        <div className="t">Verdict Score</div>
      </div>
    </div>
  );
}

// Equity curve (larger)
function EquityCurve({ h = 100, color = "#26D9B3" }) {
  const pts = useMemo(() => {
    const out = []; let v = 40;
    for (let i = 0; i < 60; i++) { v += (Math.sin(i/6)+1)*0.8 + (Math.random()-0.3)*2; out.push(Math.max(20,v)); }
    return out;
  }, []);
  return <Spark points={pts} color={color} h={h} w={320}/>;
}

// Trade rows (journal)
function TradeRows() {
  const rows = [
    { sym: "TSLA", side: "LONG", pnl: "+$1,200", pos:true, t:"09:34" },
    { sym: "AAPL", side: "SHORT", pnl: "-$400", pos:false, t:"10:12" },
    { sym: "GOOGL", side: "LONG", pnl: "-$890", pos:false, t:"11:47" },
    { sym: "NVDA", side: "LONG", pnl: "+$2,100", pos:true, t:"13:02" },
    { sym: "MSFT", side: "LONG", pnl: "+$640", pos:true, t:"14:28" },
  ];
  return (
    <div style={{display:"flex",flexDirection:"column",gap:6}}>
      {rows.map((r,i)=>(
        <div key={i} style={{display:"flex",alignItems:"center",justifyContent:"space-between",
          padding:"10px 12px",borderRadius:10,background:"rgba(10,11,26,.6)",border:"1px solid var(--b-sub)"}}>
          <div style={{display:"flex",alignItems:"center",gap:10}}>
            <div style={{width:20,height:20,borderRadius:5,background:"rgba(38,217,179,.12)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:9,fontWeight:700,color:"var(--teal)"}}>{r.sym[0]}</div>
            <div className="mono" style={{fontSize:12,color:"var(--tp)",fontWeight:600}}>{r.sym}</div>
            <div style={{fontSize:10,color:"var(--tm)",letterSpacing:".1em"}}>{r.side}</div>
          </div>
          <div className="mono" style={{fontSize:12,fontWeight:600,padding:"3px 8px",borderRadius:6,
            background: r.pos ? "rgba(38,217,179,.12)" : "rgba(255,77,106,.12)",
            color: r.pos ? "var(--teal)":"var(--red)"}}>{r.pnl}</div>
        </div>
      ))}
    </div>
  );
}

// Heatmap mini
function HeatmapMini({ cols = 8, rows = 6 }) {
  const cells = useMemo(() => {
    const out = [];
    for (let i = 0; i < cols * rows; i++) {
      const v = (Math.sin(i * 0.6) + Math.cos(i * 0.31)) * 0.5;
      out.push(v);
    }
    return out;
  }, [cols, rows]);
  return (
    <div style={{display:"grid",gridTemplateColumns:`repeat(${cols},1fr)`,gap:3}}>
      {cells.map((v,i)=>{
        const pos = v > 0;
        const intensity = Math.min(1, Math.abs(v)+.2);
        const color = pos ? `rgba(38,217,179,${intensity})` : `rgba(255,77,106,${intensity})`;
        return <div key={i} style={{aspectRatio:"1",borderRadius:3,background:color}}/>;
      })}
    </div>
  );
}

// Candles mini
function CandlesMini({ n=18, h=60 }) {
  const data = useMemo(()=>{
    const out=[]; let p=50;
    for(let i=0;i<n;i++){
      const o=p; const c=p+(Math.random()-0.45)*6;
      const hi=Math.max(o,c)+Math.random()*2; const lo=Math.min(o,c)-Math.random()*2;
      out.push({o,c,hi,lo}); p=c;
    }
    return out;
  },[n]);
  const all = data.flatMap(d=>[d.hi,d.lo]);
  const min = Math.min(...all), max = Math.max(...all);
  const range = max-min;
  const W = 160;
  const cw = W/n;
  return (
    <svg width="100%" viewBox={`0 0 ${W} ${h}`} style={{display:"block"}}>
      {data.map((d,i)=>{
        const up = d.c>=d.o;
        const color = up ? "#26D9B3" : "#FF4D6A";
        const x = i*cw + cw/2;
        const y = v => h - ((v-min)/range)*(h-4) - 2;
        return (
          <g key={i}>
            <line x1={x} x2={x} y1={y(d.hi)} y2={y(d.lo)} stroke={color} strokeWidth="1" opacity=".7"/>
            <rect x={x-cw*.35} y={Math.min(y(d.o),y(d.c))} width={cw*.7} height={Math.max(1.5,Math.abs(y(d.o)-y(d.c)))} fill={color} opacity=".9"/>
          </g>
        );
      })}
    </svg>
  );
}

// Avatars for testimonials (letter avatar with gradient)
function Avatar({ name, seed = 0 }) {
  const initials = name.split(" ").map(w=>w[0]).slice(0,2).join("").toUpperCase();
  const palettes = [
    "linear-gradient(135deg,#26D9B3,#5B6CFF)",
    "linear-gradient(135deg,#C13CFF,#5B6CFF)",
    "linear-gradient(135deg,#FFB547,#FF4D6A)",
    "linear-gradient(135deg,#4FFFD2,#C13CFF)",
    "linear-gradient(135deg,#5B6CFF,#26D9B3)",
  ];
  return (
    <div style={{width:38,height:38,borderRadius:"50%",background:palettes[seed%palettes.length],
      display:"flex",alignItems:"center",justifyContent:"center",color:"#0A0B1A",fontWeight:700,fontSize:14,
      boxShadow:"0 0 0 1.5px rgba(255,255,255,.1)"}}>{initials}</div>
  );
}

window.TickerNum = TickerNum;
window.Spark = Spark;
window.VerdictRing = VerdictRing;
window.EquityCurve = EquityCurve;
window.TradeRows = TradeRows;
window.HeatmapMini = HeatmapMini;
window.CandlesMini = CandlesMini;
window.Avatar = Avatar;
