// Bottom sections
const PERIODS = ["1D", "7D", "30D", "90D"];

const PeriodBar = ({ period, setPeriod, range, onApplyCustom }) => {
  const { t } = useLang();
  const [showCustom, setShowCustom] = useState(false);
  const [fromDate, setFromDate] = useState("");
  const [toDate, setToDate] = useState("");
  const ref = useRef(null);
  useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setShowCustom(false); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, []);
  const periodLabel = { "1D": "p_1d", "7D": "p_7d", "30D": "p_30d", "90D": "p_90d", "Custom": "p_custom" };

  return (
    <div className="period-bar">
      <div className="period-meta">
        <Icon name="calendar" size={12} />
        <span>{range}</span>
        <span style={{ color: "var(--text-4)" }}>·</span>
        <span>{t(periodLabel[period] || "p_7d")}</span>
      </div>
      <div ref={ref} style={{ position: "relative", display: "flex", gap: 8 }}>
        <div className="segmented">
          {PERIODS.map(p => (
            <button key={p} className={period === p ? "active" : ""} onClick={() => setPeriod(p)}>{p}</button>
          ))}
          <button className={period === "Custom" ? "active" : ""} onClick={() => setShowCustom(s => !s)}>Custom</button>
        </div>
        {showCustom && (
          <div className="popover">
            <div style={{ fontSize: 11, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600, marginBottom: 8 }}>{t("custom_range")}</div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 10 }}>
              <div className="field" style={{ margin: 0 }}>
                <label>{t("from")}</label>
                <input className="input" type="date" value={fromDate} onChange={e => setFromDate(e.target.value)} />
              </div>
              <div className="field" style={{ margin: 0 }}>
                <label>{t("to")}</label>
                <input className="input" type="date" value={toDate} onChange={e => setToDate(e.target.value)} />
              </div>
            </div>
            <div style={{ display: "flex", justifyContent: "flex-end", gap: 6 }}>
              <button className="btn ghost" onClick={() => setShowCustom(false)}>{t("cancel_btn")}</button>
              <button className="btn primary" onClick={() => {
                if (fromDate && toDate) { onApplyCustom(fromDate, toDate); setShowCustom(false); }
              }}>{t("apply")}</button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

// ---------- Analytics ----------
const AnalyticsRow = ({ analytics, account, prevAnalytics }) => {
  const { t } = useLang();
  const winPct = (analytics?.winRate || 0) * 100;
  const winR = 28, winC = 2 * Math.PI * winR;
  const winOffset = winC * (1 - (analytics?.winRate || 0));
  const a = analytics || { netPnl: 0, realizedPnl: 0, fees: 0, wins: 0, losses: 0, total: 0, best: null, worst: null };
  const prev = prevAnalytics;

  const eqRef = account?.equity || 0;
  const showEqPct = eqRef >= 10;
  const eqPct = showEqPct ? (a.netPnl / eqRef) * 100 : null;

  // Дельты vs предыдущий период
  const deltaPnl = prev ? (a.netPnl - prev.netPnl) : null;
  const deltaWR = prev ? (a.winRate * 100 - prev.winRate * 100) : null;
  const deltaTrades = prev ? (a.total - prev.total) : null;

  const fmtDelta = (v, dp = 2, suffix = "") => v === null ? null :
    <span className={"mono " + (v >= 0 ? "pos" : "neg")} style={{ fontSize: 11 }}>
      {v >= 0 ? "+" : ""}{v.toFixed(dp)}{suffix} <span style={{ color: "var(--text-4)", fontSize: 10 }}>{t("vs_prev")}</span>
    </span>;

  return (
    <div className="stats-grid">
      <div className="stat-card">
        <div className="stat-label">{t("net_pnl")}</div>
        <div className={"stat-big " + (a.netPnl >= 0 ? "pos" : "neg")}>
          {fmtSigned(a.netPnl)} <span style={{ fontSize: 13, color: "var(--text-3)" }}>USDT</span>
        </div>
        <div className="stat-sub">
          {showEqPct ? (
            <>
              <span className={a.netPnl >= 0 ? "pos" : "neg"}>
                <Icon name={a.netPnl >= 0 ? "arrowUp" : "arrowDown"} size={11} style={{ verticalAlign: "middle" }} />
                {" "}{fmtPct(eqPct)}
              </span>
              <span style={{ color: "var(--text-4)" }}>· {t("vs_equity")}</span>
            </>
          ) : (
            <span style={{ color: "var(--text-4)" }}>—</span>
          )}
        </div>
        {fmtDelta(deltaPnl, 2, "$") && <div style={{ marginTop: 4 }}>{fmtDelta(deltaPnl, 2, "$")}</div>}
      </div>

      <div className="stat-card">
        <div className="stat-label">{t("win_rate")}</div>
        <div className="ring" style={{ flex: 1 }}>
          <svg width="68" height="68">
            <circle className="ring-track" cx="34" cy="34" r={winR} strokeWidth="6" fill="none" />
            <circle className="ring-bar" cx="34" cy="34" r={winR} strokeWidth="6" fill="none"
              stroke={(a.winRate || 0) >= 0.5 ? "var(--long)" : "var(--warn)"}
              strokeDasharray={winC} strokeDashoffset={winOffset} strokeLinecap="round" />
          </svg>
          <div style={{ display: "flex", flexDirection: "column" }}>
            <span className="stat-big" style={{ fontSize: 22 }}>{winPct.toFixed(0)}<span style={{ fontSize: 13, color: "var(--text-3)" }}>%</span></span>
            <span className="mono" style={{ fontSize: 11, color: "var(--text-3)", marginTop: 2 }}>{a.wins} {t("w_short")} · {a.losses} {t("l_short")}</span>
            {fmtDelta(deltaWR, 1, "%")}
          </div>
        </div>
      </div>

      <div className="stat-card">
        <div className="stat-label">{t("best_worst")}</div>
        <div className="split" style={{ flex: 1 }}>
          <div className="split-cell">
            <span className="k pos" style={{ display: "flex", alignItems: "center", gap: 4 }}><Icon name="trending" size={10} /> {t("best")}</span>
            <span className="v pos">{a.best ? fmtSigned(a.best.pnl) : "—"}</span>
            {a.best?.sym && (
              <span className="mono" style={{ fontSize: 10.5, color: "var(--text-3)", display: "flex", alignItems: "center", gap: 4 }}>
                <CoinIcon sym={a.best.sym} size={11} /> {a.best.sym} · {a.best.side}
              </span>
            )}
          </div>
          <div className="split-divider" />
          <div className="split-cell">
            <span className="k neg" style={{ display: "flex", alignItems: "center", gap: 4 }}><Icon name="arrowDown" size={10} /> {t("worst")}</span>
            <span className="v neg">{a.worst ? fmtSigned(a.worst.pnl) : "—"}</span>
            {a.worst?.sym && (
              <span className="mono" style={{ fontSize: 10.5, color: "var(--text-3)", display: "flex", alignItems: "center", gap: 4 }}>
                <CoinIcon sym={a.worst.sym} size={11} /> {a.worst.sym} · {a.worst.side}
              </span>
            )}
          </div>
        </div>
      </div>

      <div className="stat-card">
        <div className="stat-label">{t("trades")}</div>
        <div className="stat-big">{a.total}</div>
        <div className="stat-sub">
          <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
            <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--long)" }} />
            {a.wins} {t("wins")}
          </span>
          <span style={{ color: "var(--text-4)" }}>·</span>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
            <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--short)" }} />
            {a.losses} {t("losses")}
          </span>
        </div>
        {fmtDelta(deltaTrades, 0)}
      </div>
    </div>
  );
};

// ---------- Equity curve ----------
const EquityChart = ({ data, period }) => {
  const { t } = useLang();
  const wrap = useRef(null);
  const svgRef = useRef(null);
  const [dim, setDim] = useState({ w: 1200, h: 240 });
  const [hover, setHover] = useState(null);

  // Наблюдаем за самим SVG: dim.w = реальная DOM-ширина SVG,
  // viewBox использует те же координаты — курсор и точки совпадают.
  useLayoutEffect(() => {
    if (!svgRef.current) return;
    const update = () => {
      if (!svgRef.current) return;
      const r = svgRef.current.getBoundingClientRect();
      if (r.width > 0) setDim({ w: r.width, h: 240 });
    };
    update();
    const ro = new ResizeObserver(update);
    ro.observe(svgRef.current);
    return () => ro.disconnect();
  }, []);

  if (!data || data.length < 2) {
    return (
      <div className="chart-wrap">
        <div className="chart-head">
          <div className="section-title" style={{ margin: 0 }}><Icon name="activity" size={11} /> {t("equity_curve")}</div>
        </div>
        <div style={{ padding: "30px 0", textAlign: "center", color: "var(--text-3)", fontSize: 12 }}>
          {t("no_data_range")}
        </div>
      </div>
    );
  }

  const { w, h } = dim;
  const padL = 8, padR = 8, padT = 8, padB = 22;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;
  const min = Math.min(...data.map(d => d.v));
  const max = Math.max(...data.map(d => d.v));
  const start = data[0].v;
  const range = max - min || 1;

  const points = data.map((d, i) => [
    padL + (i / (data.length - 1)) * innerW,
    padT + (1 - (d.v - min) / range) * innerH,
  ]);
  const startY = padT + (1 - (start - min) / range) * innerH;
  const pathD = points.map(([x, y], i) => (i === 0 ? "M" : "L") + x.toFixed(1) + " " + y.toFixed(1)).join(" ");
  const areaD = pathD + ` L ${padL + innerW} ${padT + innerH} L ${padL} ${padT + innerH} Z`;

  const last = data[data.length - 1].v;
  const delta = last - start;
  const deltaPct = start > 0 ? (delta / start) * 100 : 0;
  const isUp = delta >= 0;
  const color = isUp ? "var(--long)" : "var(--short)";

  const gridY = [0.25, 0.5, 0.75].map(t2 => padT + t2 * innerH);

  const onMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    // ratio считаем в DOM-системе (0..1 ширины SVG)
    const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
    const i = Math.max(0, Math.min(data.length - 1, Math.round(ratio * (data.length - 1))));
    setHover({ i, ...(points[i] && { x: points[i][0], y: points[i][1] }) });
  };

  return (
    <div className="chart-wrap" ref={wrap} style={{ position: "relative" }}>
      <div className="chart-head">
        <div>
          <div className="section-title" style={{ margin: 0 }}><Icon name="activity" size={11} /> {t("equity_curve")}</div>
          <div style={{ display: "flex", alignItems: "baseline", gap: 10, marginTop: 4 }}>
            <span className="h-val">{fmtMoney(last)} <span style={{ fontSize: 12, color: "var(--text-3)" }}>USDT</span></span>
            <span className={"mono " + (isUp ? "pos" : "neg")} style={{ fontSize: 12 }}>{fmtSigned(delta)} ({fmtPct(deltaPct)})</span>
          </div>
        </div>
        <div className="h-sub">
          <span style={{ color: "var(--text-4)" }}>{data.length} {t("pts")}</span>
        </div>
      </div>

      <svg ref={svgRef} className="chart-svg" viewBox={`0 0 ${w} ${h}`} style={{ height: h, width: "100%", display: "block" }}
        preserveAspectRatio="none"
        onMouseMove={onMove} onMouseLeave={() => setHover(null)}>
        <defs>
          <linearGradient id="eqfill" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={isUp ? "#34d399" : "#fb7185"} stopOpacity="0.18" />
            <stop offset="100%" stopColor={isUp ? "#34d399" : "#fb7185"} stopOpacity="0" />
          </linearGradient>
        </defs>
        {gridY.map((y, i) => (
          <line key={i} x1={padL} y1={y} x2={padL + innerW} y2={y} stroke="var(--border)" strokeWidth="1" strokeDasharray="2 4" />
        ))}
        <line x1={padL} y1={startY} x2={padL + innerW} y2={startY} stroke="var(--text-4)" strokeWidth="1" strokeDasharray="2 3" opacity="0.6" />
        <path d={areaD} fill="url(#eqfill)" />
        <path d={pathD} fill="none" stroke={color} strokeWidth="1.75" strokeLinejoin="round" strokeLinecap="round" />
        {hover && hover.x !== undefined && (
          <g>
            <line x1={hover.x} y1={padT} x2={hover.x} y2={padT + innerH} stroke="var(--text-3)" strokeWidth="1" strokeDasharray="3 3" />
            <circle cx={hover.x} cy={hover.y} r="4" fill={color} stroke="var(--bg-0)" strokeWidth="2" />
          </g>
        )}
      </svg>

      {hover && hover.x !== undefined && (
        <div className="crosshair-tip" style={{
          left: Math.min(dim.w - 180, Math.max(0, hover.x + 12)),
          top: Math.max(8, hover.y - 8),
        }}>
          <div style={{ fontSize: 13, fontWeight: 500 }}>{fmtMoney(data[hover.i].v)} <span style={{ color: "var(--text-3)", fontSize: 10 }}>USDT</span></div>
          <div style={{ fontSize: 10.5, color: (data[hover.i].v - start) >= 0 ? "var(--long)" : "var(--short)" }}>
            {fmtSigned(data[hover.i].v - start)} ({fmtPct(start > 0 ? ((data[hover.i].v - start) / start) * 100 : 0)})
          </div>
        </div>
      )}
    </div>
  );
};

// ---------- Leaderboard ----------
const Leaderboard = ({ data }) => {
  const { t } = useLang();
  const cols = [
    { key: "mostTraded", title: t("most_traded"), icon: "flame", rows: data.mostTraded, rightFmt: r => r.count + " " + t("trades_short"), rightCls: "" },
    { key: "topProfit", title: t("top_profit"), icon: "trophy", rows: data.topProfit, rightFmt: r => fmtSigned(r.pnl), rightCls: "pos" },
    { key: "topLoss", title: t("top_loss"), icon: "skull", rows: data.topLoss, rightFmt: r => fmtSigned(r.pnl), rightCls: "neg" },
  ];
  return (
    <div className="lb-grid">
      {cols.map(c => (
        <div key={c.key} className="lb-card">
          <h3><Icon name={c.icon} size={12} /> {c.title}</h3>
          <div className="lb-list">
            {c.rows.length === 0 && (
              <div className="muted mono" style={{ fontSize: 11, padding: "12px 0", textAlign: "center" }}>{t("no_data_range")}</div>
            )}
            {c.rows.map((r, i) => (
              <div key={r.sym + i} className="lb-row">
                <span className="lb-rank">#{i + 1}</span>
                <span className="lb-sym"><CoinIcon sym={r.sym} size={16} /> {r.sym}</span>
                <span className="lb-count">{r.count}{t("trades_short")} · {fmtSigned(r.pnl, 0)}</span>
                <span className={"lb-val " + c.rightCls}>{c.rightFmt(r)}</span>
              </div>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
};

// ---------- Closed trades table (с пагинацией) ----------
const PAGE_SIZE = 20;
const ClosedTradesTable = ({ trades }) => {
  const { t } = useLang();
  const [shown, setShown] = useState(PAGE_SIZE);
  // Сбрасываем счётчик при смене набора сделок
  useEffect(() => { setShown(PAGE_SIZE); }, [trades]);

  if (!trades.length) {
    return <EmptyCard title={t("no_closed")} msg={t("no_closed_msg")} />;
  }
  const visible = trades.slice(0, shown);
  const remaining = trades.length - visible.length;

  return (
    <div className="card" style={{ overflow: "auto" }}>
      <table className="tbl">
        <thead>
          <tr>
            <th>{t("opened")}</th>
            <th>{t("closed_col")}</th>
            <th>{t("duration")}</th>
            <th>{t("symbol")}</th>
            <th>{t("side")}</th>
            <th className="num">{t("qty")}</th>
            <th className="num">{t("entry_exit")}</th>
            <th className="num">{t("fee")}</th>
            <th className="num" style={{ minWidth: 140 }}>{t("pnl")}</th>
          </tr>
        </thead>
        <tbody>
          {visible.map(tr => (
            <tr key={tr.id} className={tr.partial ? "partial-row" : ""}>
              <td className="mono muted" style={{ fontSize: 11.5 }}>
                {tr.partial ? (
                  <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
                    <span className="partial-badge" title={t("partial_tooltip")}>✱</span>
                    {fmtTime(tr.openT) || "—"}
                  </span>
                ) : fmtTime(tr.openT)}
              </td>
              <td className="mono" style={{ fontSize: 11.5 }}>{fmtTime(tr.closeT)}</td>
              <td>
                <span className="pill neutral" style={{ fontFamily: "var(--font-mono)" }}>
                  <Icon name="clock" size={9} /> {fmtDur(tr.dur)}
                </span>
              </td>
              <td><span className="sym"><CoinIcon sym={tr.sym} /> {tr.sym}-PERP</span></td>
              <td><SidePill side={tr.side} /></td>
              <td className="num mono">{tr.qty}</td>
              <td className="num mono">
                <span>{fmtPrice(tr.entry)}</span>
                <span className="arrow"><Icon name="arrowRight" size={11} /></span>
                <span>{fmtPrice(tr.exit)}</span>
              </td>
              <td className="num mono muted">{fmtMoney(tr.fee)}</td>
              <td className="num">
                <div className={"mono " + (tr.pnl >= 0 ? "pos" : "neg")} style={{ fontSize: 14, fontWeight: 500 }}>{fmtSigned(tr.pnl)}</div>
                <div className="mono muted" style={{ fontSize: 10.5 }}>{fmtPct(tr.pnlPct)}</div>
              </td>
            </tr>
          ))}
          {remaining > 0 && (
            <tr className="load-more-row">
              <td colSpan={9}>
                <button className="load-more-btn" onClick={() => setShown(s => s + PAGE_SIZE)}>
                  {t("load_more")} (+{Math.min(PAGE_SIZE, remaining)})
                </button>
                <div className="muted mono" style={{ fontSize: 10.5, marginTop: 6 }}>
                  {visible.length} {t("shown_of")} {trades.length}
                </div>
              </td>
            </tr>
          )}
        </tbody>
      </table>
    </div>
  );
};

// ---------- Daily PnL bars ----------
const DailyPnLBars = ({ daily }) => {
  const { t } = useLang();
  const wrapRef = useRef(null);
  const [hover, setHover] = useState(null);  // { i, x, y } в DOM-пикселях относительно wrap

  if (!daily || daily.length === 0) return null;

  const max = Math.max(1, ...daily.map(d => Math.abs(d.pnl)));
  const barWidth = 100 / daily.length;
  const total = daily.reduce((s, d) => s + d.pnl, 0);

  const onMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
    const i = Math.min(daily.length - 1, Math.floor(ratio * daily.length));
    const wrapRect = wrapRef.current.getBoundingClientRect();
    setHover({
      i,
      x: e.clientX - wrapRect.left,
      y: e.clientY - wrapRect.top,
    });
  };

  return (
    <div className="daily-bars" ref={wrapRef} style={{ position: "relative" }}>
      <div className="daily-bars-head">
        <div className="section-title" style={{ margin: 0 }}><Icon name="barchart" size={11} /> {t("daily_pnl")}</div>
        <div className="mono muted" style={{ fontSize: 11 }}>{daily.length} days · {t("avg")} <span className={total >= 0 ? "pos" : "neg"}>{fmtSigned(total / daily.length)}</span></div>
      </div>
      <svg className="daily-bars-svg" viewBox="0 0 100 60" preserveAspectRatio="none"
        style={{ height: 60 }}
        onMouseMove={onMove}
        onMouseLeave={() => setHover(null)}>
        <line x1="0" y1="30" x2="100" y2="30" stroke="var(--border)" strokeWidth="0.3" strokeDasharray="0.5 0.5" />
        {daily.map((d, i) => {
          const h = (Math.abs(d.pnl) / max) * 28;
          const x = i * barWidth;
          const y = d.pnl >= 0 ? 30 - h : 30;
          const isHover = hover && hover.i === i;
          return (
            <rect
              key={d.date}
              x={x + barWidth * 0.1} y={y}
              width={barWidth * 0.8} height={Math.max(0.4, h)}
              fill={d.pnl >= 0 ? "var(--long)" : "var(--short)"}
              opacity={isHover ? 1 : 0.85}
            />
          );
        })}
      </svg>
      {hover && daily[hover.i] && (
        <div className="crosshair-tip" style={{
          left: Math.min((wrapRef.current?.clientWidth || 500) - 180, Math.max(8, hover.x + 12)),
          top: Math.max(8, hover.y - 56),
        }}>
          <div style={{ fontSize: 10, color: "var(--text-3)", marginBottom: 2 }}>{daily[hover.i].date}</div>
          <div style={{ fontSize: 13, fontWeight: 500 }} className={daily[hover.i].pnl >= 0 ? "pos" : "neg"}>
            {fmtSigned(daily[hover.i].pnl)} <span style={{ color: "var(--text-3)", fontSize: 10 }}>USDT</span>
          </div>
          <div style={{ fontSize: 10.5, color: "var(--text-3)" }}>
            {daily[hover.i].trades} {t("trades_short")} · <span className="pos">{daily[hover.i].wins}W</span> · <span className="neg">{daily[hover.i].losses}L</span>
          </div>
        </div>
      )}
    </div>
  );
};

// ---------- Long vs Short row ----------
const LongShortRow = ({ longStats, shortStats }) => {
  const { t } = useLang();
  const card = (stats, side, color) => (
    <div className="ls-card">
      <div className="ls-head">
        <div className="ls-title">
          <SidePill side={side} />
          {side === "LONG" ? t("long_side") : t("short_side")}
        </div>
        <div className="mono muted" style={{ fontSize: 11 }}>{stats.trades} {t("trades_short")}</div>
      </div>
      <div className="ls-body">
        <div className={"ls-pnl " + (stats.pnl >= 0 ? "pos" : "neg")}>{fmtSigned(stats.pnl)}</div>
        <div className="ls-meta">
          <div style={{ color: "var(--text-3)", fontSize: 10 }}>{t("win_rate").toUpperCase()}</div>
          <div className="mono" style={{ fontSize: 14, color: "var(--text)" }}>{(stats.win_rate || 0).toFixed(0)}%</div>
        </div>
        <div className="ls-meta">
          <div style={{ color: "var(--text-3)", fontSize: 10 }}>W / L</div>
          <div className="mono" style={{ fontSize: 13, color: "var(--text)" }}><span className="pos">{stats.wins}</span> / <span className="neg">{stats.losses}</span></div>
        </div>
      </div>
    </div>
  );
  return (
    <div className="ls-row">
      {card(longStats || { trades: 0, pnl: 0, wins: 0, losses: 0, win_rate: 0 }, "LONG")}
      {card(shortStats || { trades: 0, pnl: 0, wins: 0, losses: 0, win_rate: 0 }, "SHORT")}
    </div>
  );
};

// ---------- PnL calendar (Github-style) ----------
const PnLCalendar = ({ daily, period }) => {
  const { t } = useLang();
  const wrapRef = useRef(null);
  const [hover, setHover] = useState(null);  // { idx, x, y }

  const weeks = period === "1D" ? 1 : period === "7D" ? 2 : period === "30D" ? 6 : 14;
  const totalDays = weeks * 7;
  const today = new Date();
  const endDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
  const startDay = new Date(endDay.getTime() - (totalDays - 1) * 86400000);

  const map = new Map();
  (daily || []).forEach(d => map.set(d.date, d));

  const cells = [];
  for (let i = 0; i < totalDays; i++) {
    const dt = new Date(startDay.getTime() + i * 86400000);
    const key = dt.toISOString().slice(0, 10);
    const entry = map.get(key);
    cells.push({
      date: key, dt,
      pnl: entry ? entry.pnl : null,
      trades: entry ? entry.trades : 0,
      wins: entry ? entry.wins : 0,
      losses: entry ? entry.losses : 0,
    });
  }

  const pnls = cells.map(c => c.pnl).filter(v => v !== null);
  const maxAbs = Math.max(1, ...pnls.map(v => Math.abs(v)));

  const colorFor = (pnl) => {
    if (pnl === null) return "var(--panel-2)";
    if (pnl === 0) return "var(--border-2)";
    const intensity = Math.min(1, Math.abs(pnl) / maxAbs);
    const opacity = 0.25 + intensity * 0.7;
    const base = pnl > 0 ? "52, 211, 153" : "251, 113, 133";
    return `rgba(${base}, ${opacity.toFixed(2)})`;
  };

  const onCellEnter = (idx, e) => {
    const wrapRect = wrapRef.current.getBoundingClientRect();
    setHover({ idx, x: e.clientX - wrapRect.left, y: e.clientY - wrapRect.top });
  };

  const hovered = hover ? cells[hover.idx] : null;

  return (
    <div className="cal-wrap" ref={wrapRef} style={{ position: "relative" }}>
      <div className="cal-head">
        <div className="section-title" style={{ margin: 0 }}><Icon name="calendar" size={11} /> {t("calendar")}</div>
        <div className="mono muted" style={{ fontSize: 11 }}>{weeks} weeks</div>
      </div>
      <div className="cal-grid" onMouseLeave={() => setHover(null)}>
        {cells.map((c, idx) => (
          <div key={c.date} className="cal-cell"
            style={{ background: colorFor(c.pnl) }}
            onMouseEnter={(e) => onCellEnter(idx, e)}
            onMouseMove={(e) => onCellEnter(idx, e)}
          />
        ))}
      </div>
      <div className="cal-legend">
        <span>{t("cal_less")}</span>
        <div className="cal-legend-cells">
          <span style={{ background: "var(--panel-2)" }} />
          <span style={{ background: "rgba(251,113,133,0.6)" }} />
          <span style={{ background: "rgba(251,113,133,0.85)" }} />
          <span style={{ background: "var(--border-2)" }} />
          <span style={{ background: "rgba(52,211,153,0.6)" }} />
          <span style={{ background: "rgba(52,211,153,0.85)" }} />
        </div>
        <span>{t("cal_more")}</span>
      </div>
      {hovered && (
        <div className="crosshair-tip" style={{
          left: Math.min((wrapRef.current?.clientWidth || 500) - 180, Math.max(8, hover.x + 14)),
          top: Math.max(8, hover.y - 60),
        }}>
          <div style={{ fontSize: 10, color: "var(--text-3)", marginBottom: 2 }}>{hovered.date}</div>
          {hovered.pnl !== null ? (
            <>
              <div style={{ fontSize: 13, fontWeight: 500 }} className={hovered.pnl >= 0 ? "pos" : "neg"}>
                {fmtSigned(hovered.pnl)} <span style={{ color: "var(--text-3)", fontSize: 10 }}>USDT</span>
              </div>
              <div style={{ fontSize: 10.5, color: "var(--text-3)" }}>
                {hovered.trades} {t("trades_short")} · <span className="pos">{hovered.wins}W</span> · <span className="neg">{hovered.losses}L</span>
              </div>
            </>
          ) : (
            <div style={{ fontSize: 11, color: "var(--text-3)" }}>No trades</div>
          )}
        </div>
      )}
    </div>
  );
};


// ---------- Skeletons ----------
const SkeletonCards = ({ count = 4 }) => (
  <div className="stats-grid">
    {Array.from({ length: count }).map((_, i) => (
      <div key={i} className="stat-card">
        <div className="skel-bar" style={{ width: 70, marginBottom: 12 }} />
        <div className="skel-bar" style={{ width: 140, height: 24, marginBottom: 8 }} />
        <div className="skel-bar" style={{ width: 100, height: 10, marginTop: "auto" }} />
      </div>
    ))}
  </div>
);

const SkeletonRows = ({ rows = 6, cols = 9 }) => (
  <div className="card">
    <table className="tbl">
      <tbody>
        {Array.from({ length: rows }).map((_, i) => (
          <tr key={i}>
            {Array.from({ length: cols }).map((_, j) => (
              <td key={j}><div className="skel-bar" style={{ width: j === 0 ? "70%" : "55%", height: 11 }} /></td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  </div>
);

const SkeletonChart = ({ height = 240 }) => (
  <div className="chart-wrap">
    <div className="chart-head">
      <div>
        <div className="skel-bar" style={{ width: 100, marginBottom: 6 }} />
        <div className="skel-bar" style={{ width: 160, height: 22 }} />
      </div>
    </div>
    <div style={{ padding: "0 16px" }}>
      <div className="skel-bar" style={{ width: "100%", height: height - 60, marginTop: 10 }} />
    </div>
  </div>
);

// ---------- Risk metrics card ----------
const RiskMetricsRow = ({ riskMetrics }) => {
  const { t } = useLang();
  const m = riskMetrics;
  if (!m) return null;
  const fmtSec = (s) => {
    if (!s) return "—";
    if (s < 60) return s + "с";
    if (s < 3600) return Math.floor(s / 60) + "м";
    if (s < 86400) return Math.floor(s / 3600) + "ч " + Math.floor((s % 3600) / 60) + "м";
    return Math.floor(s / 86400) + "д " + Math.floor((s % 86400) / 3600) + "ч";
  };
  const pfClass = m.profit_factor > 1.5 ? "pos" : m.profit_factor > 1 ? "" : "neg";
  return (
    <div className="stats-grid">
      <div className="stat-card">
        <div className="stat-label">{t("max_drawdown")}</div>
        <div className="stat-big neg">−{fmtMoney(m.max_drawdown)}<span style={{ fontSize: 13, color: "var(--text-3)" }}> USDT</span></div>
        <div className="stat-sub">−{fmtMoney(m.max_drawdown_pct)}% от пика</div>
      </div>
      <div className="stat-card">
        <div className="stat-label">{t("profit_factor")}</div>
        <div className={"stat-big " + pfClass}>{fmtMoney(m.profit_factor, 2)}</div>
        <div className="stat-sub">wins / |losses|</div>
      </div>
      <div className="stat-card">
        <div className="stat-label">{t("avg_rr")}</div>
        <div className="stat-big">{m.avg_rr ? m.avg_rr.toFixed(2) : "—"}</div>
        <div className="stat-sub">avg win % / avg loss %</div>
      </div>
      <div className="stat-card">
        <div className="stat-label">{t("avg_hold")}</div>
        <div className="stat-big">{fmtSec(m.avg_holding_sec)}</div>
        <div className="stat-sub">{t("expectancy")}: <span className={m.expectancy >= 0 ? "pos" : "neg"}>{fmtSigned(m.expectancy)}</span></div>
      </div>
    </div>
  );
};

// ---------- Streaks card ----------
const StreaksCard = ({ streaks }) => {
  const { t } = useLang();
  if (!streaks) return null;
  const curType = streaks.current.type;
  const curColor = curType === "win" ? "var(--long)" : curType === "loss" ? "var(--short)" : "var(--text-3)";
  return (
    <div className="ls-row" style={{ gridTemplateColumns: "1fr 1fr 1fr" }}>
      <div className="ls-card">
        <div className="ls-head">
          <div className="ls-title"><Icon name="activity" size={11} /> {t("current_streak")}</div>
        </div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
          <span className="ls-pnl" style={{ color: curColor }}>{streaks.current.count}</span>
          <span className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>
            {curType === "none" ? t("none") : t(curType === "win" ? "win" : "loss")} подряд
          </span>
        </div>
      </div>
      <div className="ls-card">
        <div className="ls-head">
          <div className="ls-title pos"><Icon name="trophy" size={11} /> {t("longest_win")}</div>
        </div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
          <span className="ls-pnl pos">{streaks.longest_win.count}</span>
          <span className="mono pos" style={{ fontSize: 13 }}>{fmtSigned(streaks.longest_win.pnl)}</span>
        </div>
      </div>
      <div className="ls-card">
        <div className="ls-head">
          <div className="ls-title neg"><Icon name="skull" size={11} /> {t("longest_loss")}</div>
        </div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
          <span className="ls-pnl neg">{streaks.longest_loss.count}</span>
          <span className="mono neg" style={{ fontSize: 13 }}>{fmtSigned(streaks.longest_loss.pnl)}</span>
        </div>
      </div>
    </div>
  );
};

// ---------- Size to balance card ----------
const SizeToBalanceCard = ({ stb }) => {
  const { t } = useLang();
  if (!stb) return null;
  const warnColor = stb.warning === "high" ? "var(--short)" :
                    stb.warning === "medium" ? "var(--warn)" : "var(--long)";
  return (
    <div className="stat-card" style={{ borderColor: warnColor }}>
      <div className="stat-label" style={{ color: warnColor }}>{t("capital_used")}</div>
      <div className="stat-big" style={{ color: warnColor }}>
        {fmtMoney(stb.used_pct, 1)}<span style={{ fontSize: 13, color: "var(--text-3)" }}>%</span>
      </div>
      <div className="stat-sub" style={{ flexDirection: "column", alignItems: "flex-start", gap: 2 }}>
        <span>{fmtMoney(stb.used_margin)} / {fmtMoney(stb.equity)} USDT</span>
        <span>{stb.open_positions} {t("open_pos_count")} · {t("notional")} {fmtMoney(stb.total_notional)}</span>
      </div>
    </div>
  );
};

// ---------- Month calendar — настоящие месячные сетки ----------
const MONTH_NAMES_RU = ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"];
const MONTH_NAMES_EN = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const DOW_LABELS_RU = ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"];
const DOW_LABELS_EN = ["M", "T", "W", "T", "F", "S", "S"];

const MonthCalendar = ({ daily, period, onDayClick }) => {
  const { t, lang } = useLang();
  const wrapRef = useRef(null);
  const [hover, setHover] = useState(null);  // {idx, x, y, day}

  const MONTH_NAMES = lang === "ru" ? MONTH_NAMES_RU : MONTH_NAMES_EN;
  const DOW_LABELS = lang === "ru" ? DOW_LABELS_RU : DOW_LABELS_EN;

  // Период → сколько месяцев показать
  const monthsCount = period === "1D" ? 1 : period === "7D" ? 1
                     : period === "30D" ? 2 : period === "90D" ? 3 : 3;

  // Сегодня и месяцы для отображения (текущий и N-1 предыдущих)
  const today = new Date();
  const todayKey = today.toISOString().slice(0, 10);

  // Daily PnL → map: YYYY-MM-DD → {pnl, trades, wins, losses}
  const dailyMap = new Map();
  (daily || []).forEach(d => dailyMap.set(d.date, d));

  // Считаем maxAbs PnL для нормализации цветов
  const pnls = (daily || []).map(d => d.pnl).filter(v => v !== null && v !== undefined);
  const maxAbs = Math.max(1, ...pnls.map(v => Math.abs(v)));

  const colorFor = (pnl) => {
    if (pnl === null || pnl === undefined) return "var(--panel-2)";
    if (Math.abs(pnl) < 0.01) return "var(--border-2)";
    const intensity = Math.min(1, Math.abs(pnl) / maxAbs);
    const opacity = 0.25 + intensity * 0.7;
    const base = pnl > 0 ? "52, 211, 153" : "251, 113, 133";
    return `rgba(${base}, ${opacity.toFixed(2)})`;
  };

  // Список месяцев для рендера (от старшего к младшему)
  const months = [];
  for (let i = monthsCount - 1; i >= 0; i--) {
    const d = new Date(today.getFullYear(), today.getMonth() - i, 1);
    months.push(d);
  }

  // Сумма за месяц
  const monthSum = (year, month) => {
    let sum = 0, days = 0;
    for (let [k, v] of dailyMap.entries()) {
      const [y, m] = k.split("-");
      if (parseInt(y) === year && parseInt(m) === month + 1) {
        sum += v.pnl;
        days++;
      }
    }
    return { sum, days };
  };

  return (
    <div className="month-cal-wrap" ref={wrapRef} style={{ position: "relative" }}>
      <div className="month-cal-head">
        <div className="section-title" style={{ margin: 0 }}>
          <Icon name="calendar" size={11}/> {t("calendar")}
        </div>
        <div className="mono muted" style={{ fontSize: 11 }}>{monthsCount} {monthsCount === 1 ? "month" : "months"}</div>
      </div>
      <div className="month-cal-grid">
        {months.map((m, idx) => {
          const year = m.getFullYear();
          const month = m.getMonth();
          const ms = monthSum(year, month);
          // Первый день месяца → день недели (0=Mon в наших labels, JS getDay() 0=Sun)
          const firstDay = new Date(year, month, 1);
          const dowFirst = (firstDay.getDay() + 6) % 7;  // 0=Пн, 6=Вс
          const daysInMonth = new Date(year, month + 1, 0).getDate();
          const cells = [];
          for (let i = 0; i < dowFirst; i++) cells.push(null);
          for (let d = 1; d <= daysInMonth; d++) cells.push(d);

          return (
            <div key={idx} className="month-card">
              <div className="month-card-title">
                <span>{MONTH_NAMES[month]} {year}</span>
                <span className={"mono " + (ms.sum > 0 ? "pos" : ms.sum < 0 ? "neg" : "")}>
                  {ms.sum !== 0 ? fmtSigned(ms.sum) : "—"}
                </span>
              </div>
              <div className="month-dow">
                {DOW_LABELS.map((dow, i) => <span key={i}>{dow}</span>)}
              </div>
              <div className="month-days">
                {cells.map((d, i) => {
                  if (d === null) return <div key={i} className="month-day empty" />;
                  const key = `${year}-${String(month + 1).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
                  const data = dailyMap.get(key);
                  const isToday = key === todayKey;
                  return (
                    <div
                      key={i}
                      className={"month-day " + (data ? "has-trades " : "") + (isToday ? "today" : "")}
                      style={{ background: data ? colorFor(data.pnl) : undefined }}
                      onClick={() => data && onDayClick && onDayClick(key)}
                      onMouseEnter={(e) => {
                        if (!wrapRef.current) return;
                        const rect = wrapRef.current.getBoundingClientRect();
                        setHover({ key, x: e.clientX - rect.left, y: e.clientY - rect.top, data });
                      }}
                      onMouseLeave={() => setHover(null)}
                    >
                      <span style={{ position: "absolute", top: 1, right: 3, fontSize: 9, color: "var(--text-3)" }}>{d}</span>
                      {data && Math.abs(data.pnl) >= 0.1 && (
                        <div className="month-day-pnl" style={{ color: data.pnl >= 0 ? "var(--long)" : "var(--short)" }}>
                          {data.pnl >= 0 ? "+" : ""}{Math.round(data.pnl)}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>

      {hover?.data && (
        <div className="crosshair-tip" style={{
          left: Math.min((wrapRef.current?.clientWidth || 500) - 180, Math.max(8, hover.x + 14)),
          top: Math.max(8, hover.y - 60),
        }}>
          <div style={{ fontSize: 10, color: "var(--text-3)", marginBottom: 2 }}>{hover.key}</div>
          <div style={{ fontSize: 13, fontWeight: 500 }} className={hover.data.pnl >= 0 ? "pos" : "neg"}>
            {fmtSigned(hover.data.pnl)} <span style={{ color: "var(--text-3)", fontSize: 10 }}>USDT</span>
          </div>
          <div style={{ fontSize: 10.5, color: "var(--text-3)" }}>
            {hover.data.trades} {t("trades_short")} · <span className="pos">{hover.data.wins}W</span> · <span className="neg">{hover.data.losses}L</span>
          </div>
        </div>
      )}
    </div>
  );
};

Object.assign(window, {
  PeriodBar, AnalyticsRow, EquityChart, Leaderboard, ClosedTradesTable, PERIODS,
  DailyPnLBars, LongShortRow, PnLCalendar, MonthCalendar,
  SkeletonCards, SkeletonRows, SkeletonChart,
  RiskMetricsRow, StreaksCard, SizeToBalanceCard,
});
