/* =====================================================
   Betting Tracker — hand-built SVG charts
   No chart library. Brand-styled: hairline grid, profit
   green line + soft green fill, red for negative, tabular
   axis labels. Matches the site's custom canvas/SVG look.
   ===================================================== */

const GREEN = "#3ad07f";
const REDC = "#e0706a";
const DIMC = "rgba(245,246,248,0.55)";
const HAIR = "rgba(255,255,255,0.09)";

/* ---- Equity curve: area + line over settled bets ---- */
function EquityCurve({ series, currency, height = 260, fmtVal }) {
  const fv = fmtVal || ((v) => TRK.fmtMoney(TRK.round(v, 0), currency));
  const wrapRef = useRef(null);
  const [w, setW] = useState(720);
  const [hover, setHover] = useState(null);
  useEffect(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver((es) => { for (const e of es) setW(e.contentRect.width); });
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);

  const pts = series.points;
  const H = height, padL = 58, padR = 16, padT = 16, padB = 28;
  const iw = Math.max(80, w - padL - padR), ih = H - padT - padB;
  const vals = pts.map((p) => p.equity);
  let lo = Math.min.apply(null, vals), hi = Math.max.apply(null, vals);
  if (lo === hi) { lo -= 1; hi += 1; }
  const span = hi - lo, padY = span * 0.12;
  lo -= padY; hi += padY;
  const n = pts.length;
  const x = (i) => padL + (n <= 1 ? iw / 2 : (i / (n - 1)) * iw);
  const y = (v) => padT + (1 - (v - lo) / (hi - lo)) * ih;

  const line = pts.map((p, i) => (i ? "L" : "M") + x(i).toFixed(1) + " " + y(p.equity).toFixed(1)).join(" ");
  const area = line + " L" + x(n - 1).toFixed(1) + " " + (padT + ih) + " L" + x(0).toFixed(1) + " " + (padT + ih) + " Z";

  // y gridlines (4)
  const ticks = [];
  for (let i = 0; i <= 4; i++) { const v = lo + (i / 4) * (hi - lo); ticks.push(v); }
  const start = pts[0] ? pts[0].equity : 0;
  const up = series.end >= start;

  const onMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const mx = e.clientX - rect.left;
    let best = 0, bd = Infinity;
    for (let i = 0; i < n; i++) { const d = Math.abs(x(i) - mx); if (d < bd) { bd = d; best = i; } }
    setHover(best);
  };

  return (
    <div ref={wrapRef} className="trk-chart" style={{ width: "100%" }}>
      <svg width={w} height={H} onMouseMove={onMove} onMouseLeave={() => setHover(null)}
        style={{ display: "block", touchAction: "none" }}>
        <defs>
          <linearGradient id="eqfill" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={GREEN} stopOpacity="0.22" />
            <stop offset="100%" stopColor={GREEN} stopOpacity="0" />
          </linearGradient>
        </defs>
        {ticks.map((v, i) => (
          <g key={i}>
            <line x1={padL} x2={w - padR} y1={y(v)} y2={y(v)} stroke={HAIR} strokeWidth="1" />
            <text x={padL - 10} y={y(v) + 4} textAnchor="end" fontSize="10.5" fill={DIMC}
              style={{ fontVariantNumeric: "tabular-nums" }}>
              {fv(TRK.round(v, 0))}
            </text>
          </g>
        ))}
        <path d={area} fill="url(#eqfill)" />
        <path d={line} fill="none" stroke={up ? GREEN : REDC} strokeWidth="2.4"
          strokeLinejoin="round" strokeLinecap="round" />
        {/* start baseline */}
        <line x1={padL} x2={w - padR} y1={y(start)} y2={y(start)} stroke="rgba(255,255,255,0.16)"
          strokeWidth="1" strokeDasharray="3 4" />
        {hover != null && pts[hover] && (
          <g>
            <line x1={x(hover)} x2={x(hover)} y1={padT} y2={padT + ih} stroke="rgba(255,255,255,0.22)" strokeWidth="1" />
            <circle cx={x(hover)} cy={y(pts[hover].equity)} r="4.5" fill={up ? GREEN : REDC}
              stroke="#0d0d0f" strokeWidth="2" />
          </g>
        )}
        {/* x labels: first, mid, last */}
        {[0, Math.floor((n - 1) / 2), n - 1].filter((v, i, a) => a.indexOf(v) === i && pts[v]).map((i) => (
          <text key={i} x={x(i)} y={H - 8} textAnchor={i === 0 ? "start" : i === n - 1 ? "end" : "middle"}
            fontSize="10.5" fill={DIMC}>{TRK.fmtDate(pts[i].date)}</text>
        ))}
      </svg>
      {hover != null && pts[hover] && pts[hover].bet && (() => {
        // profit/loss on the day: sum of settled deltas sharing this point's date
        const d = pts[hover].date;
        const dayPL = pts.filter((p) => p.bet && p.date === d)
          .reduce((s, p) => s + TRK.betProfit(p.bet), 0);
        return (
          <div className="trk-chart__tip" style={{ left: Math.min(Math.max(x(hover), 70), w - 70) }}>
            <div className="trk-chart__tip-date">{TRK.fmtDate(d)}</div>
            <div className="trk-chart__tip-eq">{fv(pts[hover].equity)}</div>
            <div className={"trk-chart__tip-pl " + (dayPL >= 0 ? "is-pos" : "is-neg")}>
              {(dayPL >= 0 ? "+" : "") + fv(TRK.round(dayPL))}
            </div>
          </div>
        );
      })()}
    </div>
  );
}

/* ---- Period bars: profit per bucket, signed from zero ---- */
function PeriodBars({ data, currency, height = 200 }) {
  const wrapRef = useRef(null);
  const [w, setW] = useState(520);
  useEffect(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver((es) => { for (const e of es) setW(e.contentRect.width); });
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);
  const H = height, padT = 14, padB = 26, padL = 6, padR = 6;
  const ih = H - padT - padB;
  const vals = data.map((d) => d.profit);
  let hi = Math.max(0, ...vals), lo = Math.min(0, ...vals);
  if (hi === lo) { hi = 1; lo = -1; }
  const zeroY = padT + (hi / (hi - lo)) * ih;
  const n = data.length || 1;
  const slot = (w - padL - padR) / n;
  const bw = Math.min(46, slot * 0.56);
  const yFor = (v) => padT + (1 - (v - lo) / (hi - lo)) * ih;

  return (
    <div ref={wrapRef} style={{ width: "100%" }}>
      <svg width={w} height={H} style={{ display: "block" }}>
        <line x1={padL} x2={w - padR} y1={zeroY} y2={zeroY} stroke="rgba(255,255,255,0.18)" strokeWidth="1" />
        {data.map((d, i) => {
          const cx = padL + slot * i + slot / 2;
          const pos = d.profit >= 0;
          const top = pos ? yFor(d.profit) : zeroY;
          const h = Math.max(2, Math.abs(yFor(d.profit) - zeroY));
          return (
            <g key={i}>
              <rect x={cx - bw / 2} y={top} width={bw} height={h} rx="5"
                fill={pos ? GREEN : REDC} opacity={pos ? 0.9 : 0.85} />
              <text x={cx} y={H - 8} textAnchor="middle" fontSize="10.5" fill={DIMC}>{d.key}</text>
              <text x={cx} y={pos ? top - 6 : top + h + 12} textAnchor="middle" fontSize="10.5"
                fill={pos ? GREEN : REDC} style={{ fontVariantNumeric: "tabular-nums", fontWeight: 700 }}>
                {(d.profit >= 0 ? "+" : "\u2212") + Math.abs(Math.round(d.profit))}
              </text>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

/* ---- Horizontal segment bars (ROI by sport/market/etc) ---- */
function SegmentBars({ rows, currency, valueKey = "roi", metric = "roi", dual }) {
  const maxAbs = Math.max(1, ...rows.map((r) => Math.abs(r[valueKey])));
  return (
    <div className="trk-segbars">
      {rows.map((r, i) => {
        const v = r[valueKey];
        const pos = v >= 0;
        const pct = (Math.abs(v) / maxAbs) * 100;
        return (
          <div className={"trk-segbar" + (dual ? " trk-segbar--dual" : "")} key={i}>
            <div className="trk-segbar__name" title={r.key}>{r.key}</div>
            <div className="trk-segbar__track">
              <div className="trk-segbar__mid"></div>
              <div className={"trk-segbar__fill " + (pos ? "is-pos" : "is-neg")}
                style={{ width: pct / 2 + "%", [pos ? "left" : "right"]: "50%" }}></div>
            </div>
            {dual ? (
              <React.Fragment>
                <div className={"trk-segbar__val " + (r.roi >= 0 ? "is-pos" : "is-neg") + (valueKey === "roi" ? "" : " trk-segbar__val--mut")}>
                  {TRK.fmtSignedPct(r.roi, 1)}
                </div>
                <div className={"trk-segbar__val " + (r.profit >= 0 ? "is-pos" : "is-neg") + (valueKey === "profit" ? "" : " trk-segbar__val--mut")}>
                  {TRK.fmtMoney(TRK.round(r.profit, 0), currency)}
                </div>
              </React.Fragment>
            ) : (
              <div className={"trk-segbar__val " + (pos ? "is-pos" : "is-neg")}>
                {metric === "profit" ? TRK.fmtMoney(TRK.round(v, 0), currency) : TRK.fmtSignedPct(v, 1)}
              </div>
            )}
            <div className="trk-segbar__n">{r.n}</div>
          </div>
        );
      })}
    </div>
  );
}

/* ---- Donut: win / loss / push ---- */
function Donut({ won, lost, push, size = 120 }) {
  const total = won + lost + push || 1;
  const R = size / 2, r = R - 10, C = 2 * Math.PI * r;
  const segs = [
    { v: won, c: GREEN }, { v: lost, c: REDC }, { v: push, c: "#6f7178" }
  ].filter((s) => s.v > 0);
  let acc = 0;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={R} cy={R} r={r} fill="none" stroke="rgba(255,255,255,0.08)" strokeWidth="10" />
      {segs.map((s, i) => {
        const frac = s.v / total;
        const dash = frac * C;
        const el = (
          <circle key={i} cx={R} cy={R} r={r} fill="none" stroke={s.c} strokeWidth="10"
            strokeDasharray={`${dash} ${C - dash}`} strokeDashoffset={-acc * C}
            strokeLinecap="round" transform={`rotate(-90 ${R} ${R})`} />
        );
        acc += frac;
        return el;
      })}
      <text x={R} y={R - 2} textAnchor="middle" fontSize={size * 0.16} fontWeight="800" fill="#f5f6f8"
        style={{ fontVariantNumeric: "tabular-nums" }}>{Math.round((won / total) * 100)}%</text>
      <text x={R} y={R + size * 0.115} textAnchor="middle" fontSize={size * 0.068} fill={DIMC}
        style={{ letterSpacing: "0.14em" }}>WIN RATE</text>
    </svg>
  );
}

/* ---- CLV distribution mini bars ---- */
function CLVBars({ bets, height = 150 }) {
  // bucket CLV values
  const vals = bets.map(TRK.betCLV).filter((v) => v != null);
  const buckets = [
    { lab: "<\u22123", lo: -Infinity, hi: -3 }, { lab: "\u22123..0", lo: -3, hi: 0 },
    { lab: "0..3", lo: 0, hi: 3 }, { lab: "3..6", lo: 3, hi: 6 }, { lab: ">6", lo: 6, hi: Infinity }
  ].map((b) => ({ ...b, n: vals.filter((v) => v > b.lo && v <= b.hi).length }));
  const max = Math.max(1, ...buckets.map((b) => b.n));
  return (
    <div className="trk-clvbars" style={{ height }}>
      {buckets.map((b, i) => (
        <div className="trk-clvbar" key={i}>
          <div className="trk-clvbar__col">
            <div className={"trk-clvbar__fill " + (b.hi <= 0 ? "is-neg" : "is-pos")}
              style={{ height: (b.n / max) * 100 + "%" }}>
              <span>{b.n || ""}</span>
            </div>
          </div>
          <div className="trk-clvbar__lab">{b.lab}%</div>
        </div>
      ))}
    </div>
  );
}

/* ---- Monte Carlo confidence bands ---- */
function MCBands({ mc, currency, height = 250, startLab = "today", betsLab = "bets" }) {
  const wrapRef = useRef(null);
  const [w, setW] = useState(720);
  useEffect(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver((es) => { for (const e of es) setW(e.contentRect.width); });
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);

  const H = height, padL = 58, padR = 16, padT = 14, padB = 26;
  const iw = Math.max(80, w - padL - padR), ih = H - padT - padB;
  const n = mc.bands.p50.length;
  let lo = Math.min.apply(null, mc.bands.p5), hi = Math.max.apply(null, mc.bands.p95);
  if (lo === hi) { lo -= 1; hi += 1; }
  const span = hi - lo; lo -= span * 0.06; hi += span * 0.06;
  const x = (i) => padL + (i / (n - 1)) * iw;
  const y = (v) => padT + (1 - (v - lo) / (hi - lo)) * ih;
  const line = (arr) => arr.map((v, i) => (i ? "L" : "M") + x(i).toFixed(1) + " " + y(v).toFixed(1)).join(" ");
  const band = (top, bot) => {
    let d = line(top);
    for (let i = n - 1; i >= 0; i--) d += " L" + x(i).toFixed(1) + " " + y(bot[i]).toFixed(1);
    return d + " Z";
  };
  const ticks = [];
  for (let i = 0; i <= 4; i++) ticks.push(lo + (i / 4) * (hi - lo));
  const fv = (v) => TRK.fmtMoney(TRK.round(v, 0), currency);

  return (
    <div ref={wrapRef} className="trk-chart" style={{ width: "100%" }}>
      <svg width={w} height={H} style={{ display: "block" }}>
        {ticks.map((v, i) => (
          <g key={i}>
            <line x1={padL} x2={w - padR} y1={y(v)} y2={y(v)} stroke={HAIR} strokeWidth="1" />
            <text x={padL - 10} y={y(v) + 4} textAnchor="end" fontSize="10.5" fill={DIMC}
              style={{ fontVariantNumeric: "tabular-nums" }}>{fv(v)}</text>
          </g>
        ))}
        <path d={band(mc.bands.p95, mc.bands.p5)} fill="rgba(58,208,127,0.10)" />
        <path d={band(mc.bands.p75, mc.bands.p25)} fill="rgba(58,208,127,0.16)" />
        <path d={line(mc.bands.p50)} fill="none" stroke={GREEN} strokeWidth="2.2"
          strokeLinejoin="round" strokeLinecap="round" />
        {/* start baseline */}
        <line x1={padL} x2={w - padR} y1={y(mc.start)} y2={y(mc.start)} stroke="rgba(255,255,255,0.18)"
          strokeWidth="1" strokeDasharray="3 4" />
        {/* zero (ruin) line */}
        {lo < 0 && <line x1={padL} x2={w - padR} y1={y(0)} y2={y(0)} stroke={REDC} strokeOpacity="0.55"
          strokeWidth="1" strokeDasharray="2 4" />}
        <text x={x(0)} y={H - 8} textAnchor="start" fontSize="10.5" fill={DIMC}>{startLab}</text>
        <text x={x(Math.floor((n - 1) / 2))} y={H - 8} textAnchor="middle" fontSize="10.5" fill={DIMC}>+{Math.floor((n - 1) / 2)}</text>
        <text x={x(n - 1)} y={H - 8} textAnchor="end" fontSize="10.5" fill={DIMC}>+{n - 1} {betsLab}</text>
      </svg>
    </div>
  );
}

Object.assign(window, { EquityCurve, PeriodBars, SegmentBars, Donut, CLVBars, MCBands });
