/* Overview "Market read": a plain-English, rules-based summary of what BTC is doing, with a trend
 * gauge and the charts behind it. Data comes from /api/market-read (src/market_read.js). */

const { useState: useStateMR, useEffect: useEffectMR, useRef: useRefMR } = React;

const MR_TFS = [{ id: '1h', label: '1h' }, { id: '4h', label: '4h' }, { id: '1d', label: 'Daily' }];
const MR_REFRESH_MS = 5 * 60 * 1000;

const MR_REGIME = {
  range:      { label: 'Range-bound',            kind: 'gold' },
  transition: { label: 'Between trends',         kind: 'neutral' },
  uptrend:    { label: 'Trending up',            kind: 'bull' },
  downtrend:  { label: 'Trending down',          kind: 'bear' },
};

const mrUSD = (n) => '$' + (Math.abs(n) >= 1000 ? Math.round(n).toLocaleString('en-US') : Number(n).toFixed(2));
const mrTime = (t, tf) => {
  const d = new Date(t);
  return tf === '1d'
    ? d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
    : d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });
};

// Width of a container in px, so SVG text is never stretched.
function useWidthMR(def = 560) {
  const ref = useRefMR(null);
  const [w, setW] = useStateMR(def);
  useEffectMR(() => {
    const el = ref.current;
    if (!el) return undefined;
    const set = () => setW(Math.max(200, Math.floor(el.getBoundingClientRect().width)));
    set();
    if (typeof ResizeObserver === 'undefined') return undefined;
    const ro = new ResizeObserver(set);
    ro.observe(el);
    return () => ro.disconnect();
  }, []);
  return [ref, w];
}

function mrPath(vals, x, y) {
  let d = '', pen = false;
  vals.forEach((v, i) => {
    if (v == null || !Number.isFinite(v)) { pen = false; return; }
    d += (pen ? 'L' : 'M') + x(i).toFixed(1) + ' ' + y(v).toFixed(1) + ' ';
    pen = true;
  });
  return d.trim();
}

// === Trend gauge: distribution (0) ... accumulation (100) =================
function MR_Gauge({ value, label, kind }) {
  const w = 260, h = 150, cx = w / 2, cy = 126, r = 100;
  const ang = (v) => Math.PI + (Math.PI * v) / 100;               // 0 -> left, 100 -> right
  const pt = (v, rad = r) => [cx + rad * Math.cos(ang(v)), cy + rad * Math.sin(ang(v))];
  const arc = (a, b, rad = r) => {
    const [x1, y1] = pt(a, rad), [x2, y2] = pt(b, rad);
    return `M ${x1.toFixed(1)} ${y1.toFixed(1)} A ${rad} ${rad} 0 0 1 ${x2.toFixed(1)} ${y2.toFixed(1)}`;
  };
  const [nx, ny] = pt(value, r - 14);
  const colour = kind === 'bull' ? 'var(--bull)' : kind === 'bear' ? 'var(--bear)' : 'var(--gold)';
  const segs = [
    { a: 0, b: 20, c: 'var(--bear)' }, { a: 20, b: 40, c: 'var(--bear-dim)' },
    { a: 40, b: 60, c: 'var(--gold-dim)' },
    { a: 60, b: 80, c: 'var(--bull-dim)' }, { a: 80, b: 100, c: 'var(--bull)' },
  ];
  return (
    <svg width="100%" viewBox={`0 0 ${w} ${h}`} style={{ display: 'block', maxWidth: 300, margin: '0 auto' }} role="img"
         aria-label={`Trend gauge: ${label}, ${value} out of 100`}>
      {segs.map((s, i) => <path key={i} d={arc(s.a + 0.6, s.b - 0.6)} fill="none" stroke={s.c} strokeWidth="16" opacity="0.9" />)}
      <path d={arc(Math.max(value - 2, 0), Math.min(value + 2, 100), r + 14)} fill="none" stroke={colour} strokeWidth="4" strokeLinecap="round" />
      <line x1={cx} y1={cy} x2={nx} y2={ny} stroke="var(--text)" strokeWidth="2.5" strokeLinecap="round"
            style={{ transition: 'all 0.6s ease' }} />
      <circle cx={cx} cy={cy} r="7" fill="var(--bg-elev)" stroke="var(--text)" strokeWidth="1.5" />
      <text x={cx} y={cy - 38} textAnchor="middle" fontSize="30" fontWeight="600" fontFamily="var(--font-mono)" fill="var(--text)">{value}</text>
      <text x={cx - r} y={cy + 18} textAnchor="middle" fontSize="9.5" letterSpacing="0.08em" fill="var(--bear)">DISTRIBUTION</text>
      <text x={cx + r} y={cy + 18} textAnchor="middle" fontSize="9.5" letterSpacing="0.08em" fill="var(--bull)">ACCUMULATION</text>
    </svg>
  );
}

// === Price + range zones + EMAs + Bollinger band ==========================
function MR_PriceChart({ d }) {
  const [ref, W] = useWidthMR();
  const H = 240, padL = 8, padR = 62, padT = 10, padB = 22;
  const s = d.series, n = s.c.length;
  const zones = [d.range.support, d.range.resistance, d.range.strongSupport, d.range.strongResistance].filter(Boolean);
  const all = [...s.c, ...s.bbUpper, ...s.bbLower, ...zones.flatMap((z) => [z.lo, z.hi])].filter((v) => v != null);
  const lo = Math.min(...all), hi = Math.max(...all), pad = (hi - lo) * 0.04;
  const x = (i) => padL + (i / (n - 1)) * (W - padL - padR);
  const y = (v) => padT + (1 - (v - (lo - pad)) / (hi - lo + 2 * pad)) * (H - padT - padB);
  const line = mrPath(s.c, x, y);
  const band = (() => {
    const up = [], dn = [];
    for (let i = 0; i < n; i++) if (s.bbUpper[i] != null) { up.push(`${x(i).toFixed(1)} ${y(s.bbUpper[i]).toFixed(1)}`); dn.unshift(`${x(i).toFixed(1)} ${y(s.bbLower[i]).toFixed(1)}`); }
    return up.length ? 'M' + up.join(' L') + ' L' + dn.join(' L') + ' Z' : '';
  })();
  const zoneRect = (z, fill, stroke) => z && (
    <g>
      <rect x={padL} y={y(z.hi)} width={W - padL - padR} height={Math.max(2, y(z.lo) - y(z.hi))} fill={fill} />
      <line x1={padL} x2={W - padR} y1={y(z.hi)} y2={y(z.hi)} stroke={stroke} strokeWidth="0.8" opacity="0.7" />
      <line x1={padL} x2={W - padR} y1={y(z.lo)} y2={y(z.lo)} stroke={stroke} strokeWidth="0.8" opacity="0.7" />
    </g>
  );
  const strong = (z, c) => z && <line x1={padL} x2={W - padR} y1={y((z.lo + z.hi) / 2)} y2={y((z.lo + z.hi) / 2)} stroke={c} strokeWidth="1" strokeDasharray="4 4" opacity="0.6" />;
  const tick = [0, 0.33, 0.66, 1].map((f) => Math.round(f * (n - 1)));
  const price = d.price, lastX = x(n - 1);
  return (
    <div ref={ref}>
      <svg width={W} height={H} style={{ display: 'block' }} role="img" aria-label="BTC price with support, resistance and moving averages">
        <path d={band} fill="var(--info)" opacity="0.07" />
        {zoneRect(d.range.resistance, 'var(--bear-bg)', 'var(--bear)')}
        {zoneRect(d.range.support, 'var(--bull-bg)', 'var(--bull)')}
        {strong(d.range.strongResistance, 'var(--bear)')}
        {strong(d.range.strongSupport, 'var(--bull)')}
        <path d={mrPath(s.ema50, x, y)} fill="none" stroke="var(--violet)" strokeWidth="1.3" opacity="0.9" />
        <path d={mrPath(s.ema20, x, y)} fill="none" stroke="var(--gold)" strokeWidth="1.3" opacity="0.95" />
        <path d={line} fill="none" stroke="var(--text)" strokeWidth="1.8" strokeLinejoin="round" />
        <line x1={padL} x2={W - padR} y1={y(price)} y2={y(price)} stroke="var(--text-3)" strokeWidth="0.8" strokeDasharray="2 3" />
        <circle cx={lastX} cy={y(price)} r="3.5" fill="var(--text)" />
        <g fontFamily="var(--font-mono)" fontSize="10">
          <text x={W - padR + 6} y={y(d.range.resistance.hi) + 3} fill="var(--bear)">{mrUSD(d.range.resistance.hi)}</text>
          <text x={W - padR + 6} y={y(d.range.support.lo) + 3} fill="var(--bull)">{mrUSD(d.range.support.lo)}</text>
          <rect x={W - padR + 2} y={y(price) - 8} width={58} height={16} rx="3" fill="var(--bg-elev)" stroke="var(--border)" />
          <text x={W - padR + 6} y={y(price) + 3.5} fill="var(--text)">{mrUSD(price)}</text>
        </g>
        <g fontSize="9.5" fill="var(--text-4)">
          {tick.map((i, k) => <text key={k} x={Math.min(Math.max(x(i), 30), W - padR - 30)} y={H - 6} textAnchor="middle">{mrTime(s.t[i], d.tf)}</text>)}
        </g>
      </svg>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: '4px 14px', fontSize: 10.5, color: 'var(--text-3)', marginTop: 2 }}>
        <span><i style={{ display: 'inline-block', width: 14, height: 2, background: 'var(--text)', verticalAlign: 'middle' }} /> price</span>
        <span><i style={{ display: 'inline-block', width: 14, height: 2, background: 'var(--gold)', verticalAlign: 'middle' }} /> EMA 20</span>
        <span><i style={{ display: 'inline-block', width: 14, height: 2, background: 'var(--violet)', verticalAlign: 'middle' }} /> EMA 50</span>
        <span><i style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--info)', opacity: 0.25, verticalAlign: 'middle' }} /> Bollinger Bands</span>
        <span><i style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--bull-bg)', border: '1px solid var(--bull)', verticalAlign: 'middle' }} /> support zone</span>
        <span><i style={{ display: 'inline-block', width: 10, height: 10, background: 'var(--bear-bg)', border: '1px solid var(--bear)', verticalAlign: 'middle' }} /> resistance zone</span>
      </div>
    </div>
  );
}

// === Small panels =========================================================
function MR_Mini({ title, note, value, children }) {
  return (
    <div style={{ background: 'var(--bg-card-2)', border: '1px solid var(--border-soft)', borderRadius: 8, padding: '10px 12px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 }}>
        <span style={{ fontSize: 10.5, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text-3)' }}>{title}</span>
        <span className="mono" style={{ fontSize: 12.5, color: 'var(--text)' }}>{value}</span>
      </div>
      {children}
      <div style={{ fontSize: 10.5, color: 'var(--text-4)', marginTop: 2 }}>{note}</div>
    </div>
  );
}

function MR_RSI({ d }) {
  const [ref, W] = useWidthMR(220);
  const H = 84, s = d.series.rsi, n = s.length;
  const x = (i) => (i / (n - 1)) * (W - 4) + 2, y = (v) => 4 + (1 - v / 100) * (H - 8);
  return (
    <MR_Mini title="RSI (14)" value={d.metrics.rsi.toFixed(0)} note="The 40–60 zone matters most in a range. Rising while price is flat = building strength.">
      <div ref={ref}>
        <svg width={W} height={H} style={{ display: 'block' }}>
          <rect x="0" y={y(60)} width={W} height={y(40) - y(60)} fill="var(--gold-bg)" />
          <line x1="0" x2={W} y1={y(50)} y2={y(50)} stroke="var(--text-4)" strokeDasharray="3 3" strokeWidth="0.8" />
          <line x1="0" x2={W} y1={y(70)} y2={y(70)} stroke="var(--bear)" strokeWidth="0.6" opacity="0.4" />
          <line x1="0" x2={W} y1={y(30)} y2={y(30)} stroke="var(--bull)" strokeWidth="0.6" opacity="0.4" />
          <path d={mrPath(s, x, y)} fill="none" stroke="var(--info)" strokeWidth="1.6" />
        </svg>
      </div>
    </MR_Mini>
  );
}

function MR_Volume({ d }) {
  const [ref, W] = useWidthMR(220);
  const H = 84, s = d.series, n = s.vol.length;
  const max = Math.max(...s.vol, ...s.volAvg.filter((v) => v != null)) || 1;
  const bw = Math.max(1, (W - 4) / n - 1);
  const x = (i) => 2 + (i / n) * (W - 4), y = (v) => H - 3 - (v / max) * (H - 8);
  const ratio = d.metrics.volRatio;
  return (
    <MR_Mini title="Volume" value={`${Math.round(ratio * 100)}% of avg`} note="Quiet volume is normal in a range. A breakout needs a clear volume surge to be trusted.">
      <div ref={ref}>
        <svg width={W} height={H} style={{ display: 'block' }}>
          {s.vol.map((v, i) => <rect key={i} x={x(i)} y={y(v)} width={bw} height={H - 3 - y(v)} fill={s.up[i] ? 'var(--bull)' : 'var(--bear)'} opacity="0.55" />)}
          <path d={mrPath(s.volAvg, (i) => x(i) + bw / 2, y)} fill="none" stroke="var(--gold)" strokeWidth="1.4" />
        </svg>
      </div>
    </MR_Mini>
  );
}

function MR_Line({ title, note, value, vals, colour = 'var(--info)', fill = true }) {
  const [ref, W] = useWidthMR(220);
  const H = 84, ok = vals.filter((v) => v != null), lo = Math.min(...ok), hi = Math.max(...ok), n = vals.length;
  const x = (i) => (i / (n - 1)) * (W - 4) + 2, y = (v) => 6 + (1 - (v - lo) / ((hi - lo) || 1)) * (H - 12);
  const p = mrPath(vals, x, y);
  return (
    <MR_Mini title={title} value={value} note={note}>
      <div ref={ref}>
        <svg width={W} height={H} style={{ display: 'block' }}>
          {fill && p && <path d={`${p} L${x(n - 1)} ${H} L${x(0)} ${H} Z`} fill={colour} opacity="0.12" />}
          <path d={p} fill="none" stroke={colour} strokeWidth="1.6" />
        </svg>
      </div>
    </MR_Mini>
  );
}

// === Signal rows ==========================================================
function MR_ScoreBar({ score }) {
  const pctW = Math.abs(score) * 50;
  const colour = score >= 0.2 ? 'var(--bull)' : score <= -0.2 ? 'var(--bear)' : 'var(--gold-dim)';
  return (
    <div style={{ position: 'relative', height: 6, background: 'var(--bg-elev)', borderRadius: 3, minWidth: 90 }} title={`score ${score.toFixed(2)}`}>
      <div style={{ position: 'absolute', left: '50%', top: -2, bottom: -2, width: 1, background: 'var(--border-strong)' }} />
      <div style={{ position: 'absolute', top: 0, bottom: 0, borderRadius: 3, background: colour,
                    left: score >= 0 ? '50%' : `${50 - pctW}%`, width: `${pctW}%`, transition: 'all 0.4s ease' }} />
    </div>
  );
}

function MR_Signals({ signals }) {
  const word = { bull: 'Bullish', bear: 'Bearish', neutral: 'Neutral' };
  return (
    <div>
      {signals.map((s, i) => (
        <div key={s.id} style={{ display: 'grid', gridTemplateColumns: 'minmax(120px, 160px) 110px 100px 1fr', gap: 12, alignItems: 'center',
                                 padding: '9px 0', borderTop: i ? '1px solid var(--border-soft)' : 'none' }} className="mr-signal-row">
          <span style={{ fontSize: 12.5, fontWeight: 500 }}>{s.name}</span>
          <span><span className={'chip ' + s.bias}><span className="chip-dot" /> {word[s.bias]}</span></span>
          <MR_ScoreBar score={s.score} />
          <span style={{ fontSize: 11.5, color: 'var(--text-3)', lineHeight: 1.5 }}>{s.reading.charAt(0).toUpperCase() + s.reading.slice(1)}.</span>
        </div>
      ))}
    </div>
  );
}

// === The section ==========================================================
function W_MarketRead() {
  const [tf, setTf] = useStateMR('4h');
  const [state, setState] = useStateMR({ data: null, error: null, loading: true });

  useEffectMR(() => {
    let cancelled = false, timer;
    const load = () => {
      fetch('/api/market-read?tf=' + tf)
        .then((r) => r.json())
        .then((j) => { if (!cancelled) setState({ data: j.ok ? j.data : null, error: j.ok ? null : (j.error || 'unavailable'), loading: false }); })
        .catch(() => { if (!cancelled) setState((s) => ({ ...s, error: 'unavailable', loading: false })); })
        .finally(() => { if (!cancelled) timer = setTimeout(load, MR_REFRESH_MS); });
    };
    setState((s) => ({ ...s, loading: true }));
    load();
    return () => { cancelled = true; clearTimeout(timer); };
  }, [tf]);

  const d = state.data;
  const regime = d ? (MR_REGIME[d.regime] || MR_REGIME.transition) : null;

  return (
    <div className="card" style={{ gridColumn: 'span 12' }}>
      <div className="card-h" style={{ flexWrap: 'wrap', gap: 10 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <h3 style={{ margin: 0 }}>Market read · BTC</h3>
          {regime && <span className={'chip ' + regime.kind}><span className="chip-dot" /> {regime.label}</span>}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          {d && <span style={{ fontSize: 10.5, color: 'var(--text-4)' }}>last candle closed {new Date(d.asOf).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} · closed {d.tfLabel} candles</span>}
          <div role="tablist" aria-label="Timeframe" style={{ display: 'inline-flex', border: '1px solid var(--border)', borderRadius: 7, overflow: 'hidden' }}>
            {MR_TFS.map((t) => (
              <button key={t.id} role="tab" aria-selected={tf === t.id} onClick={() => setTf(t.id)}
                style={{ padding: '4px 11px', fontSize: 11.5, border: 'none', cursor: 'pointer', fontFamily: 'var(--font-mono)',
                         background: tf === t.id ? 'var(--bg-elev)' : 'transparent', color: tf === t.id ? 'var(--text)' : 'var(--text-3)' }}>
                {t.label}
              </button>
            ))}
          </div>
        </div>
      </div>

      <div className="card-b">
        {!d && (
          <div style={{ padding: '28px 0', textAlign: 'center', color: 'var(--text-3)', fontSize: 12.5 }}>
            {state.loading ? 'Reading the market…' : 'The market read is unavailable right now. It will retry shortly.'}
          </div>
        )}

        {d && (
          <>
            <div className="rg-split" style={{ display: 'grid', gridTemplateColumns: 'minmax(240px, 300px) 1fr', gap: 22, alignItems: 'center' }}>
              <div>
                <MR_Gauge value={d.bias.gauge} label={d.bias.label} kind={d.bias.kind} />
                <div style={{ textAlign: 'center', marginTop: 4 }}>
                  <span className={'chip ' + d.bias.kind} style={{ fontSize: 12 }}><span className="chip-dot" /> {d.bias.label}</span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'center', gap: 16, marginTop: 10, fontSize: 11, color: 'var(--text-3)' }}>
                  <span>RSI <b className="mono" style={{ color: 'var(--text)' }}>{d.metrics.rsi.toFixed(0)}</b></span>
                  {d.metrics.adx != null && <span>ADX <b className="mono" style={{ color: 'var(--text)' }}>{d.metrics.adx.toFixed(0)}</b></span>}
                  <span>Volume <b className="mono" style={{ color: 'var(--text)' }}>{Math.round(d.metrics.volRatio * 100)}%</b></span>
                </div>
              </div>

              <div>
                <div style={{ fontSize: 15.5, lineHeight: 1.55, color: 'var(--text)', fontWeight: 500 }}>{d.summary}</div>
                <div style={{ fontSize: 12.5, lineHeight: 1.6, color: 'var(--text-2)', marginTop: 8 }}>{d.lineup}</div>
                <div style={{ marginTop: 12, padding: '10px 12px', borderRadius: 8, background: 'var(--gold-bg)', border: '1px solid var(--border-soft)', fontSize: 12, lineHeight: 1.6, color: 'var(--text-2)' }}>
                  <b style={{ color: 'var(--gold)' }}>What would confirm a move.</b> {d.watch}
                </div>
                <div className="rg-split" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, marginTop: 12 }}>
                  {[
                    { k: 'Resistance', v: `${mrUSD(d.range.resistance.lo)}–${mrUSD(d.range.resistance.hi)}`, c: 'var(--bear)' },
                    { k: 'Price in range', v: `${d.range.positionPct}% up the range`, c: 'var(--text)' },
                    { k: 'Support', v: `${mrUSD(d.range.support.lo)}–${mrUSD(d.range.support.hi)}`, c: 'var(--bull)' },
                  ].map((m) => (
                    <div key={m.k} style={{ background: 'var(--bg-card-2)', border: '1px solid var(--border-soft)', borderRadius: 8, padding: '8px 10px' }}>
                      <div style={{ fontSize: 10, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text-4)' }}>{m.k}</div>
                      <div className="mono" style={{ fontSize: 12.5, color: m.c, marginTop: 2 }}>{m.v}</div>
                    </div>
                  ))}
                </div>
              </div>
            </div>

            <div style={{ marginTop: 20 }}><MR_PriceChart d={d} /></div>

            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(210px, 1fr))', gap: 12, marginTop: 14 }}>
              <MR_RSI d={d} />
              <MR_Volume d={d} />
              <MR_Line title="On-balance volume" vals={d.series.obv} colour="var(--bull)"
                value={d.metrics.obvTrend || '–'}
                note="Capital flow. Rising while price is flat hints at accumulation; falling hints at distribution." />
              <MR_Line title="Band width" vals={d.series.bandwidth} colour="var(--violet)"
                value={d.metrics.squeeze ? 'squeeze' : `${window.OverviewFormat.ordinal(d.metrics.bandwidthRank)} pct`}
                note="Bollinger Band width. Very narrow = energy building, direction still unknown." />
            </div>

            <div style={{ marginTop: 18, fontSize: 10.5, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-3)' }}>The five signals behind the gauge</div>
            <MR_Signals signals={d.signals} />

            <div style={{ marginTop: 10, fontSize: 10.5, color: 'var(--text-4)', lineHeight: 1.5 }}>
              Rules-based read of Binance spot candles; it is not a prediction and not financial advice. The gauge blends structure (30%), moving averages (20%), RSI (20%), volume flow (20%) and Bollinger Bands (10%). ADX only labels the regime.
            </div>
          </>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { W_MarketRead });
