// Risk Rating + Periodic Review views.
//
// RiskRatingsView   — current customer risk ratings, distribution, factor breakdown,
//                     full customer table sortable/filterable by tier.
// PeriodicReviewView— review cadence & migration: KPIs, migration matrix,
//                     "deserves attention" list, recent reviews log.

const { useState: useRRState, useMemo: useRRMemo } = React;

// ── Shared bits ─────────────────────────────────────────────────────────────
function RatingPill({ rating, size = "md" }) {
  // map rating → color tokens
  const map = {
    severe: { bg: "var(--risk-high-bg)",   fg: "var(--risk-high)",  label: "Severe" },
    high:   { bg: "oklch(95% 0.05 35)",    fg: "oklch(56% 0.20 35)",label: "High"   },
    med:    { bg: "var(--risk-med-bg)",    fg: "var(--risk-med)",   label: "Medium" },
    low:    { bg: "var(--risk-low-bg)",    fg: "var(--risk-low)",   label: "Low"    },
  };
  // Dark-mode override for the "high" non-token color so it lifts properly
  const isDark = document.documentElement.dataset.theme === "dark";
  if (isDark && rating === "high") {
    map.high = { bg: "oklch(28% 0.08 35)", fg: "oklch(76% 0.18 35)", label: "High" };
  }
  const m = map[rating];
  const cls = size === "sm" ? "" : "";
  return (
    <span className="pill" style={{
      background: m.bg, color: m.fg,
      fontWeight: 500, letterSpacing: "0.01em",
      height: size === "sm" ? 17 : 19,
      fontSize: size === "sm" ? 10.5 : 11,
    }}>
      <span className="dot" style={{ background: m.fg, marginRight: 5 }} />
      {m.label}
    </span>
  );
}

function ScoreBadge({ score }) {
  const c = score >= 80 ? "var(--risk-high)"
          : score >= 60 ? "oklch(56% 0.20 35)"
          : score >= 35 ? "var(--risk-med)"
          : "var(--risk-low)";
  const isDark = document.documentElement.dataset.theme === "dark";
  const cLifted = isDark && score >= 60 && score < 80 ? "oklch(76% 0.18 35)" : c;
  return (
    <span className="mono" style={{ fontWeight: 500, color: cLifted, fontSize: 12.5 }}>
      {score}
    </span>
  );
}

function MiniTrend({ data, height = 22, width = 70 }) {
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const last = data[data.length - 1];
  const prev = data[0];
  const dir = last > prev ? "up" : last < prev ? "down" : "flat";
  const c = dir === "up" ? "var(--risk-high)"
          : dir === "down" ? "var(--risk-low)"
          : "var(--fg-3)";
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * (width - 2) + 1;
    const y = height - 2 - ((v - min) / range) * (height - 4);
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  });
  return (
    <svg width={width} height={height} style={{ display: "block" }}>
      <polyline points={pts.join(" ")} stroke={c} strokeWidth="1.4" fill="none"
                strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={pts[pts.length - 1].split(",")[0]}
              cy={pts[pts.length - 1].split(",")[1]} r="1.8" fill={c} />
    </svg>
  );
}

function StackedDistBar() {
  // Single horizontal bar split by tier
  const order = ["low", "med", "high", "severe"];
  const total = order.reduce((s, k) => s + RATING_DIST[k].count, 0);
  return (
    <div>
      <div style={{ display: "flex", height: 14, borderRadius: 4, overflow: "hidden",
                    border: "1px solid var(--border)" }}>
        {order.map(k => {
          const w = (RATING_DIST[k].count / total) * 100;
          return (
            <div key={k} title={`${k} · ${RATING_DIST[k].count}`}
                 style={{ width: `${w}%`, background: RATING_DIST[k].color }} />
          );
        })}
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 8, marginTop: 12 }}>
        {order.slice().reverse().map(k => (
          <div key={k}>
            <div style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 11.5, color: "var(--fg-3)" }}>
              <span className="dot" style={{ background: RATING_DIST[k].color, margin: 0 }} />
              <span style={{ textTransform: "capitalize" }}>{k === "med" ? "Medium" : k}</span>
            </div>
            <div className="mono" style={{ fontSize: 18, fontWeight: 500, marginTop: 2, color: "var(--fg)" }}>
              {RATING_DIST[k].count.toLocaleString()}
            </div>
            <div className="mono" style={{ fontSize: 11, color: "var(--fg-3)" }}>{RATING_DIST[k].pct}%</div>
          </div>
        ))}
      </div>
    </div>
  );
}

function FactorChart() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
      {FACTOR_AVG.map(f => (
        <div key={f.key} style={{ display: "grid", gridTemplateColumns: "120px 1fr 36px", gap: 10, alignItems: "center" }}>
          <span style={{ fontSize: 12.5 }}>{f.label}</span>
          <div style={{ position: "relative", height: 5, background: "var(--bg-3)", borderRadius: 3 }}>
            <div style={{
              width: `${f.value}%`, height: "100%",
              background: f.value >= 60 ? "var(--risk-high)"
                        : f.value >= 35 ? "var(--risk-med)"
                        : "var(--risk-low)",
              borderRadius: 3,
            }} />
          </div>
          <div className="mono" style={{ fontSize: 11.5, textAlign: "right" }}>{f.value}</div>
        </div>
      ))}
    </div>
  );
}

function RatingTrendChart() {
  // Stacked area chart, 12 months × 4 tiers
  const W = 720, H = 180, P = { l: 36, r: 8, t: 8, b: 22 };
  const innerW = W - P.l - P.r;
  const innerH = H - P.t - P.b;
  const data = RATING_TREND;
  const total = (m) => m.low + m.med + m.high + m.severe;
  const maxTotal = Math.max(...data.map(total));
  // Y for each tier stack (cumulative from low at bottom up to severe at top)
  const colors = {
    low: "var(--risk-low)",
    med: "var(--risk-med)",
    high: "oklch(56% 0.20 35)",
    severe: "var(--risk-high)",
  };
  const isDark = document.documentElement.dataset.theme === "dark";
  if (isDark) colors.high = "oklch(76% 0.18 35)";

  const buildArea = (key, prevKey) => {
    const upper = data.map((d, i) => {
      const x = P.l + (i / (data.length - 1)) * innerW;
      const y = P.t + innerH - (cum(d, key) / maxTotal) * innerH;
      return [x, y];
    });
    const lower = data.slice().reverse().map((d, i) => {
      const realI = data.length - 1 - i;
      const x = P.l + (realI / (data.length - 1)) * innerW;
      const y = P.t + innerH - (cum(d, prevKey) / maxTotal) * innerH;
      return [x, y];
    });
    return upper.concat(lower)
      .map((p, i) => (i === 0 ? "M" : "L") + p[0].toFixed(1) + " " + p[1].toFixed(1))
      .join(" ") + " Z";
  };
  const cum = (d, key) => {
    if (key === "low") return d.low;
    if (key === "med") return d.low + d.med;
    if (key === "high") return d.low + d.med + d.high;
    if (key === "severe") return d.low + d.med + d.high + d.severe;
    return 0;
  };

  // Y axis grid lines
  const yTicks = [0, Math.round(maxTotal / 2), maxTotal];

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H}>
      {/* Y grid */}
      {yTicks.map((t, i) => {
        const y = P.t + innerH - (t / maxTotal) * innerH;
        return (
          <g key={i}>
            <line x1={P.l} y1={y} x2={W - P.r} y2={y} stroke="var(--border)" strokeDasharray={i === 0 ? "" : "2 3"} />
            <text x={P.l - 6} y={y + 3} fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)" textAnchor="end">
              {t === 0 ? "0" : t >= 1000 ? (t/1000).toFixed(1) + "k" : t}
            </text>
          </g>
        );
      })}
      {/* Stacks: low at bottom up */}
      <path d={"M" + (P.l) + " " + (P.t + innerH) +
               " " + data.map((d, i) => "L" + (P.l + (i / (data.length - 1)) * innerW) + " " + (P.t + innerH - (d.low / maxTotal) * innerH)).join(" ") +
               " L" + (W - P.r) + " " + (P.t + innerH) + " Z"}
            fill={colors.low} opacity="0.85" />
      <path d={buildArea("med", "low")} fill={colors.med} opacity="0.85" />
      <path d={buildArea("high", "med")} fill={colors.high} opacity="0.85" />
      <path d={buildArea("severe", "high")} fill={colors.severe} opacity="0.85" />
      {/* X labels */}
      {data.map((d, i) => (
        <text key={i} x={P.l + (i / (data.length - 1)) * innerW} y={H - 6}
              fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)" textAnchor="middle">
          {d.m}
        </text>
      ))}
      {/* Legend */}
      <g transform={`translate(${W - 200}, ${P.t + 4})`}>
        {["severe","high","med","low"].map((k, i) => (
          <g key={k} transform={`translate(0, ${i * 14})`}>
            <rect width="10" height="10" fill={colors[k]} rx="2" />
            <text x="14" y="9" fontSize="10.5" fontFamily="var(--font-sans)" fill="var(--fg-2)">
              {k === "med" ? "Medium" : k[0].toUpperCase() + k.slice(1)}
            </text>
          </g>
        ))}
      </g>
    </svg>
  );
}

// ── Risk Ratings view ───────────────────────────────────────────────────────
function mapRiskProfileToCustomer(p) {
  const score = Math.round(Number(p.risk_score || 0));
  let rating = "low";
  if (score >= 80) rating = "severe";
  else if (score >= 60) rating = "high";
  else if (score >= 35) rating = "med";
  return {
    id: p.entity_id,
    name: p.entity_id,
    type: p.entity_type === "business" ? "business" : "person",
    country: "—",
    segment: "Live · " + p.entity_type,
    onboarded: "—",
    rating,
    score,
    prior: "low",
    priorScore: Math.max(0, score - 10),
    lastReview: p.last_transaction_at ? p.last_transaction_at.slice(0, 10) : "—",
    nextReview: "—",
    overdue: false,
    factors: { geo: 30, type: 40, product: 50, behavior: score },
    trend: [Math.max(0, score - 20), Math.max(0, score - 15), Math.max(0, score - 10), Math.max(0, score - 5), score],
    flagged: score >= 60,
    reviewer: "System",
    reasons: p.risk_factors || ["Live risk profile"],
    _raw: p,
  };
}

function RiskRatingsView({ onOpenCustomer, data }) {
  const liveProfiles = (data?.riskProfiles || []).map(mapRiskProfileToCustomer);
  const customers = liveProfiles.length ? liveProfiles : CUSTOMERS;
  const [tier, setTier] = useRRState("all");
  const [sortBy, setSortBy] = useRRState("score");

  const counts = useRRMemo(() => ({
    all:    customers.length,
    severe: customers.filter(c => c.rating === "severe").length,
    high:   customers.filter(c => c.rating === "high").length,
    med:    customers.filter(c => c.rating === "med").length,
    low:    customers.filter(c => c.rating === "low").length,
    flagged:customers.filter(c => c.flagged).length,
  }), [customers]);

  const filtered = useRRMemo(() => {
    let r = customers;
    if (tier === "severe") r = r.filter(c => c.rating === "severe");
    else if (tier === "high") r = r.filter(c => c.rating === "high");
    else if (tier === "med") r = r.filter(c => c.rating === "med");
    else if (tier === "low") r = r.filter(c => c.rating === "low");
    else if (tier === "flagged") r = r.filter(c => c.flagged);
    r = [...r].sort((a, b) =>
      sortBy === "score"   ? b.score - a.score
    : sortBy === "delta"   ? (b.score - b.priorScore) - (a.score - a.priorScore)
    : sortBy === "name"    ? a.name.localeCompare(b.name)
    : a.lastReview < b.lastReview ? 1 : -1);
    return r;
  }, [tier, sortBy, customers]);

  return (
    <>
      <div className="tabs">
        <button className={`tab ${tier === "all" ? "active" : ""}`} onClick={() => setTier("all")}>
          All <span className="tab-count">{counts.all.toLocaleString()}</span>
        </button>
        <button className={`tab ${tier === "severe" ? "active" : ""}`} onClick={() => setTier("severe")}>
          Severe <span className="tab-count">{counts.severe}</span>
        </button>
        <button className={`tab ${tier === "high" ? "active" : ""}`} onClick={() => setTier("high")}>
          High <span className="tab-count">{counts.high}</span>
        </button>
        <button className={`tab ${tier === "med" ? "active" : ""}`} onClick={() => setTier("med")}>
          Medium <span className="tab-count">{counts.med}</span>
        </button>
        <button className={`tab ${tier === "low" ? "active" : ""}`} onClick={() => setTier("low")}>
          Low <span className="tab-count">{counts.low}</span>
        </button>
        <button className={`tab ${tier === "flagged" ? "active" : ""}`} onClick={() => setTier("flagged")}
                style={{ marginLeft: 12 }}>
          <Icon.Flag size={11} /> Flagged for review <span className="tab-count">{counts.flagged}</span>
        </button>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1.2fr 1fr 1fr", gap: 12, padding: 18 }}>
        <div className="card">
          <div className="card-hd">
            <h3>Population distribution</h3>
            <span className="spacer" />
            <span className="mono muted" style={{ fontSize: 11 }}>1,288 rated customers</span>
          </div>
          <div className="card-body">
            <StackedDistBar />
          </div>
        </div>
        <div className="card">
          <div className="card-hd">
            <h3>Avg factor contribution</h3>
            <span className="spacer" />
            <span className="mono muted" style={{ fontSize: 11 }}>population mean</span>
          </div>
          <div className="card-body">
            <FactorChart />
          </div>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          {[
            { k: "severe",   l: "Severe",   v: RR_KPIS.severe,   c: "var(--risk-high)" },
            { k: "newHigh",  l: "New high · 30d", v: RR_KPIS.newHigh,  c: "oklch(56% 0.20 35)" },
            { k: "rerated",  l: "Re-rated · MTD", v: RR_KPIS.reratedMTD, c: "var(--fg)" },
            { k: "pending",  l: "Pending refresh", v: RR_KPIS.pendingRefresh, c: "var(--risk-med)" },
          ].map(({ k, l, v, c }) => (
            <div key={k} className="card" style={{ padding: 14 }}>
              <div className="kpi-label">{l}</div>
              <div className="mono" style={{ fontSize: 22, fontWeight: 500, color: c, letterSpacing: "-0.02em", marginTop: 4 }}>
                {v.value}
              </div>
              <div className="kpi-delta" style={{
                color: String(v.delta).startsWith("−") || String(v.delta).startsWith("-")
                  ? "var(--risk-low)" : "var(--fg-3)",
                marginTop: 2,
              }}>
                {v.delta} this month
              </div>
            </div>
          ))}
        </div>
      </div>

      <div style={{ padding: "0 18px 12px" }}>
        <div className="card">
          <div className="card-hd" style={{ gap: 10 }}>
            <h3>Customer ratings</h3>
            <span className="spacer" />
            <select className="field" value={sortBy} onChange={e => setSortBy(e.target.value)} style={{ width: 170 }}>
              <option value="score">Sort: Score (high → low)</option>
              <option value="delta">Sort: Largest change</option>
              <option value="name">Sort: Name</option>
              <option value="review">Sort: Recently reviewed</option>
            </select>
          </div>
          <table className="tbl">
            <thead>
              <tr>
                <th style={{ width: 140 }}>Customer ID</th>
                <th>Name · Segment</th>
                <th style={{ width: 110 }}>Tenant</th>
                <th style={{ width: 80 }}>Rating</th>
                <th style={{ width: 70 }}>Score</th>
                <th style={{ width: 100 }}>Δ vs prior</th>
                <th style={{ width: 220 }}>Factor profile</th>
                <th style={{ width: 100 }}>Trend · 8mo</th>
                <th style={{ width: 110 }}>Last review</th>
                <th style={{ width: 110 }}>Next review</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map(c => {
                const delta = c.score - c.priorScore;
                const deltaUp = delta > 0;
                const tierChanged = c.rating !== c.prior;
                return (
                  <tr key={c.id} className={c.flagged ? "flagged" : ""}
                      onClick={() => onOpenCustomer?.(c)}>
                    <td>
                      <span className="mono" style={{ fontSize: 11.5, fontWeight: 500 }}>{c.id}</span>
                      <div className="mono" style={{ fontSize: 10.5, color: "var(--fg-3)" }}>{c.country}</div>
                    </td>
                    <td>
                      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        <span style={{
                          display: "inline-grid", placeItems: "center",
                          width: 22, height: 22, borderRadius: 4,
                          background: "var(--bg-3)", color: "var(--fg-2)",
                        }}>
                          {c.type === "business" ? <Icon.Building size={12} /> : <Icon.Person size={12} />}
                        </span>
                        <div style={{ minWidth: 0, lineHeight: 1.3 }}>
                          <div style={{ fontWeight: 500 }}>{c.name}</div>
                          <div style={{ color: "var(--fg-3)", fontSize: 11.5 }}>{c.segment}</div>
                        </div>
                      </div>
                    </td>
                    <td>
                      <TenantChip tenant={tenantForCustomer(c.name)} />
                    </td>
                    <td>
                      <div>
                        <RatingPill rating={c.rating} />
                        {tierChanged && (
                          <div style={{ display: "flex", alignItems: "center", gap: 3, marginTop: 2, fontSize: 10, color: "var(--fg-3)" }}>
                            from <span style={{ textTransform: "capitalize" }}>{c.prior === "med" ? "med" : c.prior}</span>
                            <Icon.ArrowR size={9} />
                          </div>
                        )}
                      </div>
                    </td>
                    <td>
                      <ScoreBadge score={c.score} />
                      <div className="mono" style={{ fontSize: 10.5, color: "var(--fg-3)", marginTop: 1 }}>/100</div>
                    </td>
                    <td>
                      <span className="mono" style={{
                        fontSize: 11.5, fontWeight: 500,
                        color: deltaUp ? "var(--risk-high)" : delta < 0 ? "var(--risk-low)" : "var(--fg-3)",
                        display: "inline-flex", alignItems: "center", gap: 3,
                      }}>
                        {deltaUp && <Icon.ArrowUp size={10} />}
                        {delta < 0 && <Icon.ArrowDn size={10} />}
                        {delta > 0 ? "+" : ""}{delta}
                      </span>
                    </td>
                    <td>
                      <FactorRow factors={c.factors} />
                    </td>
                    <td><MiniTrend data={c.trend} /></td>
                    <td className="mono muted" style={{ fontSize: 11.5 }}>{c.lastReview}</td>
                    <td>
                      <span className="mono" style={{
                        fontSize: 11.5,
                        color: c.overdue ? "var(--risk-high)" : "var(--fg-2)",
                      }}>
                        {c.overdue && <Icon.Flag size={10} style={{ marginRight: 4 }} />}
                        {c.nextReview}
                      </span>
                      {c.overdue && (
                        <div style={{ fontSize: 10, color: "var(--risk-high)" }}>overdue</div>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
}

function FactorRow({ factors }) {
  const keys = [
    { k: "geo",      label: "Geo" },
    { k: "type",     label: "Type" },
    { k: "product",  label: "Prod" },
    { k: "behavior", label: "Beh" },
  ];
  return (
    <div style={{ display: "flex", gap: 4 }}>
      {keys.map(({ k, label }) => {
        const v = factors[k];
        const c = v >= 80 ? "var(--risk-high)"
                : v >= 60 ? "oklch(56% 0.20 35)"
                : v >= 35 ? "var(--risk-med)"
                : "var(--risk-low)";
        return (
          <div key={k} title={`${label} · ${v}`} style={{ flex: 1, minWidth: 0 }}>
            <div style={{ height: 3, background: "var(--bg-3)", borderRadius: 2 }}>
              <div style={{ width: `${v}%`, height: "100%", background: c, borderRadius: 2 }} />
            </div>
            <div className="mono" style={{ fontSize: 9.5, color: "var(--fg-3)", marginTop: 2, textAlign: "center" }}>
              {label}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ── Periodic Review view ────────────────────────────────────────────────────

const TIER_IDX = { low: 0, med: 1, high: 2, severe: 3 };

function ChangeArrow({ prior, next, scoreDelta }) {
  const dx = TIER_IDX[next] - TIER_IDX[prior];
  const upgraded = dx > 0; // upgraded = worse (higher tier)
  const downgraded = dx < 0;
  const c = upgraded ? "var(--risk-high)" : downgraded ? "var(--risk-low)" : "var(--fg-3)";
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
      <RatingPill rating={prior} size="sm" />
      <span style={{ color: c, display: "inline-flex", alignItems: "center" }}>
        <Icon.ArrowR size={11} />
      </span>
      <RatingPill rating={next} size="sm" />
      {scoreDelta != null && (
        <span className="mono" style={{
          marginLeft: 4, fontSize: 11, fontWeight: 500, color: c,
        }}>
          {scoreDelta > 0 ? "+" : ""}{scoreDelta}
        </span>
      )}
    </span>
  );
}

function MigrationMatrix() {
  const rows = MIGRATION.rows;
  const cells = MIGRATION.cells;
  const max = Math.max(...cells.flat());
  const isDark = document.documentElement.dataset.theme === "dark";
  // colour intensity:
  //  cell on diagonal → neutral grey
  //  above diagonal (upgraded to worse) → red intensity
  //  below diagonal (downgraded to better) → green intensity
  const cellBg = (r, c, v) => {
    if (v === 0) return "var(--bg-2)";
    const t = v / max;
    if (isDark) {
      if (r === c) return `oklch(${18 + t * 12}% 0.008 260)`;
      if (c > r)   return `oklch(${22 + t * 30}% ${0.04 + t * 0.16} 22)`;
      return            `oklch(${22 + t * 20}% ${0.04 + t * 0.10} 155)`;
    }
    if (r === c) return `oklch(${94 - t * 18}% 0.005 260)`;
    if (c > r)   return `oklch(${94 - t * 36}% ${0.03 + t * 0.14} 22)`;
    return            `oklch(${94 - t * 24}% ${0.02 + t * 0.10} 155)`;
  };
  const cellFg = (r, c, v) => {
    if (v === 0) return "var(--fg-4)";
    if (isDark) {
      // Dark mode — text always light enough to read on the tinted bg
      if (v / max < 0.15) return "var(--fg-2)";
      return "var(--fg)";
    }
    if (c > r && v / max > 0.4) return "#fff";
    if (r === c && v / max > 0.6) return "#fff";
    return "var(--fg)";
  };
  const tierLabel = (t) => t === "med" ? "Medium" : t[0].toUpperCase() + t.slice(1);
  return (
    <div>
      <div style={{ display: "grid", gridTemplateColumns: "90px repeat(4, 1fr)", gap: 4, alignItems: "center" }}>
        <div></div>
        {rows.map(r => (
          <div key={r} style={{ textAlign: "center", fontSize: 11, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: "0.04em", fontWeight: 500 }}>
            {tierLabel(r)}
          </div>
        ))}
        {rows.map((r, ri) => (
          <React.Fragment key={r}>
            <div style={{ fontSize: 11.5, color: "var(--fg-2)", textAlign: "right", paddingRight: 8 }}>
              {tierLabel(r)}
            </div>
            {rows.map((c, ci) => {
              const v = cells[ri][ci];
              const attention = ci > ri && (ci - ri) >= 2; // big jump upwards
              return (
                <div key={c} style={{
                  height: 56,
                  background: cellBg(ri, ci, v),
                  color: cellFg(ri, ci, v),
                  borderRadius: 4,
                  display: "grid",
                  placeItems: "center",
                  position: "relative",
                  border: attention && v > 0 ? "1px solid var(--risk-high)" : "1px solid transparent",
                }}>
                  <div className="mono" style={{ fontSize: 16, fontWeight: 500, lineHeight: 1 }}>
                    {v}
                  </div>
                  {ci === ri && v > 0 && (
                    <div style={{ position: "absolute", top: 4, right: 6, fontSize: 9, color: cellFg(ri, ci, v), opacity: 0.55, textTransform: "uppercase", letterSpacing: "0.05em" }}>
                      no change
                    </div>
                  )}
                </div>
              );
            })}
          </React.Fragment>
        ))}
      </div>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 12, fontSize: 11.5 }}>
        <div style={{ color: "var(--fg-3)" }}>
          <span style={{ marginRight: 16 }}>Rows: prior rating</span>
          <span>Columns: new rating · last 30 days</span>
        </div>
        <div style={{ display: "flex", gap: 14, color: "var(--fg-3)" }}>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
            <span style={{ width: 10, height: 10, borderRadius: 2, background: "oklch(58% 0.17 22)" }} /> upgraded · worse
          </span>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
            <span style={{ width: 10, height: 10, borderRadius: 2, background: "oklch(70% 0.12 155)" }} /> downgraded · better
          </span>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
            <span style={{ width: 10, height: 10, borderRadius: 2, border: "1px solid var(--risk-high)", background: "transparent" }} /> needs attention
          </span>
        </div>
      </div>
    </div>
  );
}

function AttentionList() {
  // Filter REVIEWS where tier change is big OR is into high/severe
  const items = REVIEWS.filter(r => {
    const dx = TIER_IDX[r.new] - TIER_IDX[r.prior];
    return dx >= 1 && (r.new === "severe" || dx >= 2 || (r.new === "high" && r.prior !== "high"));
  });
  return (
    <div style={{ display: "flex", flexDirection: "column" }}>
      {items.map((r, i) => {
        const dx = TIER_IDX[r.new] - TIER_IDX[r.prior];
        const big = dx >= 2 || r.new === "severe";
        return (
          <div key={r.id} style={{
            padding: "12px 16px",
            borderTop: i === 0 ? "0" : "1px solid var(--border)",
            display: "grid",
            gridTemplateColumns: "1fr auto",
            gap: 10,
          }}>
            <div style={{ minWidth: 0 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
                <span style={{ fontWeight: 500, fontSize: 13 }}>{r.customer}</span>
                {big && <span className="pill high" style={{ fontSize: 10 }}>
                  <Icon.Bolt size={10} style={{ marginRight: 3 }} /> Attention
                </span>}
              </div>
              <div style={{ fontSize: 11.5, color: "var(--fg-3)", marginBottom: 6 }}>
                <span className="mono">{r.id}</span> · {r.reason}
              </div>
              <ChangeArrow prior={r.prior} next={r.new} scoreDelta={r.scoreDelta} />
            </div>
            <div style={{ textAlign: "right", fontSize: 11, color: "var(--fg-3)", display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 4 }}>
              <span className="mono">{r.completed}</span>
              <span>by {r.reviewer}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

function PeriodicReviewView() {
  const [tab, setTab] = useRRState("recent");
  return (
    <>
      <div className="tabs">
        <button className={`tab ${tab === "recent" ? "active" : ""}`}    onClick={() => setTab("recent")}>Recent reviews <span className="tab-count">{REVIEWS.length}</span></button>
        <button className={`tab ${tab === "due" ? "active" : ""}`}       onClick={() => setTab("due")}>Due <span className="tab-count">84</span></button>
        <button className={`tab ${tab === "overdue" ? "active" : ""}`}   onClick={() => setTab("overdue")}>Overdue <span className="tab-count" style={{ background: "var(--risk-high)", color: "#fff" }}>9</span></button>
        <button className={`tab ${tab === "schedule" ? "active" : ""}`}  onClick={() => setTab("schedule")}>Schedule</button>
      </div>

      {/* KPI strip */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 12, padding: "18px 18px 0" }}>
        {[
          { ...PR_KPIS.dueMonth,    color: "var(--accent)" },
          { ...PR_KPIS.overdue,     color: "var(--risk-high)" },
          { ...PR_KPIS.completed,   color: "var(--risk-low)" },
          { ...PR_KPIS.ratingChanges, color: "var(--fg)" },
          { ...PR_KPIS.escalations, color: "var(--risk-high)" },
          { ...PR_KPIS.avgCycle,    color: "var(--fg)" },
        ].map((k, i) => (
          <div key={i} className="card" style={{ padding: 16 }}>
            <div className="kpi-label">{k.label}</div>
            <div className="mono" style={{ fontSize: 24, fontWeight: 500, color: k.color, letterSpacing: "-0.02em", marginTop: 4 }}>
              {k.value}
            </div>
            <div className="kpi-delta" style={{
              color: String(k.delta).startsWith("−") || String(k.delta).startsWith("-")
                ? "var(--risk-low)" : "var(--fg-3)",
              marginTop: 2,
            }}>
              {k.delta} vs last month
            </div>
          </div>
        ))}
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 12, padding: 18 }}>
        <div className="card">
          <div className="card-hd">
            <h3>Rating migration · last 30 days</h3>
            <span className="spacer" />
            <span className="mono muted" style={{ fontSize: 11 }}>456 transitions</span>
          </div>
          <div className="card-body">
            <MigrationMatrix />
          </div>
        </div>
        <div className="card">
          <div className="card-hd">
            <h3>Deserves attention</h3>
            <span className="spacer" />
            <span className="pill high">
              <Icon.Bolt size={10} style={{ marginRight: 3 }} /> 6 customers
            </span>
          </div>
          <AttentionList />
        </div>
      </div>

      <div style={{ padding: "0 18px 12px" }}>
        <div className="card">
          <div className="card-hd">
            <h3>Population over 12 months · by rating tier</h3>
            <span className="spacer" />
            <span className="mono muted" style={{ fontSize: 11 }}>stacked count</span>
          </div>
          <div className="card-body" style={{ paddingTop: 4 }}>
            <RatingTrendChart />
          </div>
        </div>
      </div>

      <div style={{ padding: "0 18px 18px" }}>
        <div className="card">
          <div className="card-hd">
            <h3>Recent reviews</h3>
            <span className="spacer" />
            <span className="mono muted" style={{ fontSize: 11 }}>{REVIEWS.length} reviews · last 5 days</span>
          </div>
          <table className="tbl">
            <thead>
              <tr>
                <th style={{ width: 110 }}>Review</th>
                <th>Customer</th>
                <th style={{ width: 110 }}>Tenant</th>
                <th style={{ width: 250 }}>Rating change</th>
                <th>Reason</th>
                <th style={{ width: 110 }}>Reviewer</th>
                <th style={{ width: 140 }}>Completed</th>
              </tr>
            </thead>
            <tbody>
              {REVIEWS.map(r => (
                <tr key={r.id} className={r.flagged ? "flagged" : ""}>
                  <td><span className="mono" style={{ fontSize: 11.5, fontWeight: 500 }}>{r.id}</span></td>
                  <td><span style={{ fontWeight: 500 }}>{r.customer}</span></td>
                  <td><TenantChip tenant={tenantForCustomer(r.customer)} /></td>
                  <td><ChangeArrow prior={r.prior} next={r.new} scoreDelta={r.scoreDelta} /></td>
                  <td className="muted" style={{ fontSize: 12 }}>{r.reason}</td>
                  <td>
                    <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
                      <span style={{
                        width: 18, height: 18, borderRadius: "50%",
                        background: "var(--bg-3)", color: "var(--fg-2)",
                        display: "grid", placeItems: "center",
                        fontSize: 9, fontWeight: 600,
                      }}>{r.reviewer.split(" ").map(x => x[0]).join("").slice(0,2)}</span>
                      <span style={{ fontSize: 12 }}>{r.reviewer.split(" ")[0]}</span>
                    </span>
                  </td>
                  <td className="mono muted" style={{ fontSize: 11.5 }}>{r.completed}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
}

Object.assign(window, { RiskRatingsView, PeriodicReviewView });
