/* iBD Coliseum — Executive admin dashboard */
function Kpi({ label, value, unit, target, pct, star, ok }) {
  return (
    <div className="kpi">
      <div className="kt">{label}{star && <Icon name="sparkle" className="ic star" style={{ width: 14, height: 14 }} />}</div>
      <div className="kv">{value}{unit && <span className="unit">{unit}</span>}</div>
      <div className="ktarget">
        {ok && <span className="pill-ok"><Icon name="check" className="ic" /> </span>}
        {target}
      </div>
      {typeof pct === "number" && <div className="meterbar"><i style={{ width: Math.min(100, pct) + "%" }}></i></div>}
    </div>
  );
}

function LineChart({ data, series, max }) {
  const W = 640, H = 232, padX = 14, padR = 16, padT = 18, padB = 30;
  const n = data.length;
  const innerW = W - padX - padR, innerH = H - padT - padB;
  const xAt = (i) => padX + (i / (n - 1)) * innerW;
  const yAt = (v) => padT + innerH - (v / max) * innerH;
  const grid = [0, 0.25, 0.5, 0.75, 1];
  return (
    <svg className="linechart" viewBox={`0 0 ${W} ${H}`} role="img" aria-label="Engagement over time">
      {grid.map((g, i) => {
        const y = padT + innerH - g * innerH;
        return <line key={i} className="lc-grid" x1={padX} x2={W - padR} y1={y} y2={y} />;
      })}
      {series.map((s) => {
        const pts = data.map((d, i) => `${xAt(i)},${yAt(d[s.key])}`).join(" ");
        const last = data[n - 1][s.key];
        return (
          <g key={s.key}>
            {s.area &&
              <polygon points={`${xAt(0)},${padT + innerH} ${pts} ${xAt(n - 1)},${padT + innerH}`} fill={s.color} opacity="0.12" />}
            <polyline points={pts} fill="none" stroke={s.color} strokeWidth="2.6" strokeLinejoin="round" strokeLinecap="round" />
            {data.map((d, i) => <circle key={i} cx={xAt(i)} cy={yAt(d[s.key])} r={i === n - 1 ? 4 : 2.4} fill={s.color} />)}
            <text className="lc-end" x={xAt(n - 1) - 6} y={yAt(last) - 9} textAnchor="end" fill={s.color}>{last}</text>
          </g>
        );
      })}
      {data.map((d, i) => <text key={i} className="lc-xl" x={xAt(i)} y={H - 9} textAnchor="middle">{d.t}</text>)}
    </svg>
  );
}

// Derive every dashboard metric from the live Coliseum data (gallery cards + the
// engagement map that powers points), so the executive view reflects real activity.
function computeMetrics(cards) {
  const { CATEGORIES } = window.COLISEUM_DATA;
  const eng = window.COLISEUM_DATA.ENGAGEMENT || {};
  const engVals = Object.values(eng);
  const pilotUsers = Math.max(engVals.length, 1);

  const submitters = new Set(cards.map((c) => c.author));
  const totalUpvotes = cards.reduce((s, c) => s + (c.votes || 0), 0);
  const totalComments = cards.reduce((s, c) => s + ((c.comments && c.comments.length) || 0), 0);
  const avgVotesPerCard = cards.length ? +(totalUpvotes / cards.length).toFixed(1) : 0;

  const engagedCount = engVals.filter((e) => (e.upvotesGiven || 0) > 0 || (e.commentsMade || 0) > 0).length;
  const repeatCount = engVals.filter((e) => ((e.upvotesGiven || 0) + (e.commentsMade || 0) + (e.submissions || 0)) >= 2).length;
  const submissionRate = Math.round((submitters.size / pilotUsers) * 100);
  const engagementRate = Math.round((engagedCount / pilotUsers) * 100);
  const repeatRate = Math.round((repeatCount / pilotUsers) * 100);

  const deptMap = {};
  cards.forEach((c) => { const d = c.team || "Unassigned"; deptMap[d] = (deptMap[d] || 0) + 1; });
  const byDept = Object.entries(deptMap).map(([dept, n]) => ({ dept, n })).sort((a, b) => b.n - a.n);

  const catMap = {};
  cards.forEach((c) => { catMap[c.cat] = (catMap[c.cat] || 0) + 1; });
  const catDist = CATEGORIES.map((c) => ({ id: c.id, n: catMap[c.id] || 0 })).filter((c) => c.n > 0).sort((a, b) => b.n - a.n);

  const authorGroup = {};
  cards.forEach((c) => { if (!authorGroup[c.author]) authorGroup[c.author] = c.group || "C"; });
  const groups = Object.values(authorGroup);
  const cCount = groups.filter((g) => g === "C").length;
  const bCount = groups.filter((g) => g !== "C").length;
  const noneCount = Math.max(pilotUsers - submitters.size, 0);
  const partTotal = Math.max(cCount + bCount + noneCount, 1);
  const participation = [
    { id: "c", label: "Group C", note: "hesitant majority", color: "var(--accent)", count: cCount, pct: Math.round((cCount / partTotal) * 100) },
    { id: "b", label: "Group B", note: "early adopters", color: "#2A6FDB", count: bCount, pct: Math.round((bCount / partTotal) * 100) },
    { id: "none", label: "Not yet posted", note: "still to take the first step", color: "#D8CCB8", count: noneCount, pct: Math.round((noneCount / partTotal) * 100) },
  ];

  const dayMap = {};
  cards.forEach((c) => {
    if (!c.createdAt) return;
    const dt = new Date(c.createdAt);
    const key = dt.toISOString().slice(0, 10);
    if (!dayMap[key]) dayMap[key] = { key, t: dt.toLocaleDateString("en-US", { month: "short", day: "numeric" }), votes: 0, comments: 0 };
    dayMap[key].votes += c.votes || 0;
    dayMap[key].comments += (c.comments && c.comments.length) || 0;
  });
  const days = Object.values(dayMap).sort((a, b) => (a.key < b.key ? -1 : 1));
  let cv = 0, cc = 0;
  let activity = days.map((d) => { cv += d.votes; cc += d.comments; return { t: d.t, votes: cv, comments: cc }; });
  if (activity.length === 0) activity = [{ t: "start", votes: 0, comments: 0 }, { t: "now", votes: 0, comments: 0 }];
  else if (activity.length === 1) activity = [{ t: "start", votes: 0, comments: 0 }, activity[0]];

  const qMap = {};
  cards.forEach((c) => {
    if (!c.createdAt) return;
    const dt = new Date(c.createdAt);
    const q = `Q${Math.floor(dt.getMonth() / 3) + 1} '${String(dt.getFullYear()).slice(2)}`;
    qMap[q] = (qMap[q] || 0) + 1;
  });
  const qSort = (a, b) => {
    const pa = a.q.match(/Q(\d) '(\d+)/), pb = b.q.match(/Q(\d) '(\d+)/);
    return (+pa[2] - +pb[2]) || (+pa[1] - +pb[1]);
  };
  const now = new Date();
  const curQ = `Q${Math.floor(now.getMonth() / 3) + 1} '${String(now.getFullYear()).slice(2)}`;
  let quarterly = Object.entries(qMap).map(([q, n]) => ({ q, n })).sort(qSort);
  if (quarterly.length === 0) quarterly = [{ q: curQ, n: cards.length }];
  quarterly = quarterly.map((q) => ({ ...q, current: q.q === curQ }));
  if (!quarterly.some((q) => q.current)) quarterly[quarterly.length - 1].current = true;

  return {
    pilotUsers, submitters: submitters.size, submissionRate, engagementRate, repeatRate,
    newCardsThisQuarter: cards.length, totalUpvotes, totalComments, avgVotesPerCard,
    byDept, catDist, participation, activity, quarterly,
  };
}

function AdminDashboard({ cards, empty }) {
  const { CATEGORIES } = window.COLISEUM_DATA;
  const M = computeMetrics(cards);
  const spotlight = [...cards].sort((a, b) => b.votes - a.votes).slice(0, 5);
  const [picked, setPicked] = useState(new Set([spotlight[0]?.id, spotlight[1]?.id, spotlight[2]?.id]));
  const togglePick = (id) => setPicked(p => { const n = new Set(p); n.has(id) ? n.delete(id) : (n.size < 3 && n.add(id)); return n; });
  const catMax = Math.max(1, ...M.catDist.map(c => c.n));
  const deptMax = Math.max(1, ...M.byDept.map(d => d.n));
  const qMax = Math.max(1, ...M.quarterly.map(q => q.n));
  const qGrowth = (M.quarterly.length > 1 && M.quarterly[0].n > 0)
    ? (M.quarterly[M.quarterly.length - 1].n / M.quarterly[0].n).toFixed(1)
    : null;
  const deptsActive = M.byDept.filter(d => d.n > 0).length;

  return (
    <div className="admin">
      <section className="ahero">
        <div className="wrap">
          <div>
            <div className="eyebrow">iBD Coliseum · Executive view</div>
            <h1>Pilot health dashboard</h1>
            <p>Proof of adoption for the town hall — participation first, power users second.</p>
          </div>
          <div className="period"><Icon name="cal" className="ic" />{empty ? `Pre-launch · whole org (${M.pilotUsers})` : `Live pilot · whole org (${M.pilotUsers})`}</div>
        </div>
      </section>

      <div className="wrap admin-body">
        <div className="kpis">
          <Kpi label="Submission rate" star value={empty ? 0 : M.submissionRate} unit="%" pct={empty ? 0 : M.submissionRate / 40 * 100} ok={!empty}
            target={empty ? <>0 of {M.pilotUsers} posted · target ≥30–40%</> : <>{M.submitters} of {M.pilotUsers} posted · target ≥30–40%</>} />
          <Kpi label="Engagement rate" value={empty ? 0 : M.engagementRate} unit="%" pct={empty ? 0 : M.engagementRate} ok={!empty}
            target={<>viewed ≥3 or upvoted · target ≥60%</>} />
          <Kpi label="Repeat rate" value={empty ? 0 : M.repeatRate} unit="%" pct={empty ? 0 : M.repeatRate / 20 * 100} ok={!empty}
            target={<>2+ actions in 30d · target ≥20%</>} />
          <Kpi label="Gallery health" star value={empty ? 0 : M.newCardsThisQuarter} pct={empty ? 0 : M.newCardsThisQuarter / 15 * 100} ok={!empty}
            target={<>new cards / quarter · target ≥15</>} />
        </div>

        <div className="dash">
          {/* submissions by department */}
          <div className="dcard">
            <div className="dh">
              <h3>Submissions by department</h3>
              <span className="sub">whole org · {empty ? 0 : deptsActive} of {M.byDept.length} departments active</span>
            </div>
            {empty ?
            <EmptyState compact icon="chart" title="No submissions yet" message="Each department's activity will appear here once colleagues start posting cards." /> :
            <>
            <div className="deptbars">
              {M.byDept.map(d => (
                <div className="catbar" key={d.dept}>
                  <span className="cn">{d.dept}</span>
                  <span className="ct"><i style={{ width: (d.n / deptMax * 100) + "%" }}></i></span>
                  <span className="cc">{d.n}</span>
                </div>
              ))}
            </div>
            <p style={{ fontSize: "var(--fs-small)", color: "var(--fg-2)", marginTop: 16, lineHeight: "var(--lh-body)" }}>
              Submissions span <strong style={{ color: "var(--ink)" }}>{deptsActive} {deptsActive === 1 ? "team" : "teams"}</strong> so far{M.byDept[0] ? <>, led by <strong style={{ color: "var(--ink)" }}>{M.byDept[0].dept}</strong></> : ""}.
            </p>
            </>
            }
          </div>

          {/* participation split */}
          <div className="dcard">
            <div className="dh"><h3>Who's participating</h3><span className="sub">north-star check</span></div>
            {empty ?
            <EmptyState compact icon="users" title="No participants yet" message="Group B / Group C participation splits appear once people start contributing." /> :
            <>
            <div className="split">
              <div className="splitbar">
                {M.participation.map(s => (
                  <div key={s.id} className={s.id === "c" ? "sc" : s.id === "b" ? "sb" : "sn"} style={{ width: s.pct + "%" }}>
                    {s.pct >= 12 ? s.pct + "%" : ""}
                  </div>
                ))}
              </div>
              <div className="splegend">
                {M.participation.map(s => (
                  <div className="sl" key={s.id}>
                    <span className="sw" style={{ background: s.color }}></span>
                    <span className="lname"><b>{s.label}</b><span>{s.note}</span></span>
                    <span className="lval">{s.count}</span>
                  </div>
                ))}
              </div>
            </div>
            <div style={{ marginTop: 18, padding: "14px 16px", background: "var(--accent-wash)", borderRadius: "var(--radius-md)", fontSize: "var(--fs-small)", color: "var(--fg-1)", lineHeight: "var(--lh-body)" }}>
              <strong>{M.submitters} of {M.pilotUsers} have posted ({M.submissionRate}%).</strong> {M.participation[0].count >= M.participation[1].count ? "Group C — the hesitant majority — is taking the first step, the exact failure mode this pilot was built to avoid." : "Early adopters are leading; nudge the hesitant majority next."}
            </div>
            </>
            }
          </div>
        </div>

        <div className="dash">
          {/* engagement line chart */}
          <div className="dcard">
            <div className="dh"><h3>Engagement over the pilot</h3><span className="sub">cumulative · weekly</span></div>
            {empty ?
            <EmptyState compact icon="chart" title="No engagement yet" message="Upvotes and comments will chart here as the gallery comes to life." /> :
            <>
            <LineChart data={M.activity} max={Math.max(1, ...M.activity.map(a => a.votes))}
              series={[
                { key: "votes", label: "Upvotes", color: "var(--accent)", area: true },
                { key: "comments", label: "Comments", color: "#2A6FDB" },
              ]} />
            <div className="legend">
              <span className="li"><span className="sw" style={{ background: "var(--accent)" }}></span>Upvotes ({M.activity[M.activity.length - 1].votes})</span>
              <span className="li"><span className="sw" style={{ background: "#2A6FDB" }}></span>Comments ({M.activity[M.activity.length - 1].comments})</span>
            </div>
            </>
            }
          </div>

          {/* submissions per quarter */}
          <div className="dcard">
            <div className="dh"><h3>Submissions per quarter</h3><span className="sub">trailing 4 quarters</span></div>
            {empty ?
            <EmptyState compact icon="chart" title="No submissions yet" message="Quarter-over-quarter momentum will show here after the first cards land." /> :
            <>
            <div className="chart qchart">
              {M.quarterly.map(q => (
                <div className="col" key={q.q}>
                  <span className="cval">{q.n}</span>
                  <div className="bars" style={{ height: 150 }}>
                    <div className={"bar quarter" + (q.current ? " cur" : "")} style={{ height: (q.n / qMax * 150) }} title={`${q.n} submissions`}></div>
                  </div>
                  <span className="clabel">{q.q}</span>
                </div>
              ))}
            </div>
            <p style={{ fontSize: "var(--fs-small)", color: "var(--fg-2)", marginTop: 16, lineHeight: "var(--lh-body)" }}>
              {qGrowth
                ? <>Up <strong style={{ color: "var(--ink)" }}>{qGrowth}×</strong> since {M.quarterly[0].q} — momentum is compounding quarter over quarter.</>
                : <><strong style={{ color: "var(--ink)" }}>{M.newCardsThisQuarter}</strong> {M.newCardsThisQuarter === 1 ? "submission" : "submissions"} this quarter so far.</>}
            </p>
            </>
            }
          </div>
        </div>

        <div className="dash">
          {/* spotlight candidates */}
          <div className="dcard">
            <div className="dh">
              <h3>Weekly spotlight candidates</h3>
              <span className="sub">{picked.size}/3 picked for the town hall</span>
            </div>
            <div className="spot">
              {spotlight.length === 0 ?
              <EmptyState compact icon="sparkle" title="No candidates yet" message="The most-upvoted cards will queue up here for the town-hall spotlight." /> :
              spotlight.map((c, i) => (
                <div className={"spot-item" + (i === 0 ? " lead" : "")} key={c.id}>
                  <span className="rk">{i + 1}</span>
                  <div className="sm">
                    <div className="t">{c.title}</div>
                    <div className="a">{c.author} · {c.team} · {c.group === "C" ? "Group C" : "Group B"}</div>
                  </div>
                  <span className="sv"><Icon name="up" className="ic" />{c.votes}</span>
                  <button className="pickbtn" aria-pressed={picked.has(c.id)} onClick={() => togglePick(c.id)}>
                    {picked.has(c.id) ? "Picked" : "Pick"}
                  </button>
                </div>
              ))}
            </div>
            <p style={{ fontSize: "var(--fs-micro)", color: "var(--fg-3)", marginTop: 14 }}>
              Recognition only — no cash. Selected cards go into the weekly executive email + a live demo at team meetings.
            </p>
          </div>

          {/* health + categories */}
          <div className="dcard">
            <div className="dh"><h3>Gallery signal</h3></div>
            <div className="health">
              <div className="hs"><div className="v">{empty ? 0 : M.avgVotesPerCard}</div><div className="l">Avg upvotes / card <span className="muted">(spam check &gt;1 {empty ? "—" : "✓"})</span></div></div>
              <div className="hs"><div className="v">{empty ? 0 : M.totalUpvotes}</div><div className="l">Total upvotes given</div></div>
            </div>
            <div className="dh" style={{ marginTop: 24, marginBottom: 14 }}><h3 style={{ fontSize: "var(--fs-body)" }}>By category</h3></div>
            {empty ?
            <EmptyState compact icon="grid" title="No categories yet" message="Category mix appears as cards are posted." /> :
            <div className="catbars">
              {M.catDist.map(c => {
                const meta = CATEGORIES.find(x => x.id === c.id);
                return (
                  <div className="catbar" key={c.id}>
                    <span className="cn">{meta.label}</span>
                    <span className="ct"><i style={{ width: (c.n / catMax * 100) + "%" }}></i></span>
                    <span className="cc">{c.n}</span>
                  </div>
                );
              })}
            </div>
            }
          </div>
        </div>
      </div>
    </div>
  );
}
window.AdminDashboard = AdminDashboard;
