/* ELC Dashboard — individual views */

// ─── Overview ───────────────────────────────
function OverviewView({ narratives, setNarratives, editable }) {
  const F = DATA.admissions.forecast;
  const R = DATA.retention;
  const M = DATA.marketing;
  const cpeDrop = Math.round(((M.costPerEnrolment.current - M.costPerEnrolment.trend[0].v) / M.costPerEnrolment.trend[0].v) * 100);
  const newNeeded = F.scenarios.likely.total - F.confirmed;

  return (
    <div className="view">
      <div className="view-hd">
        <div>
          <h2>Overview <span className="scope-tag">April 2026</span></h2>
          <p>At a glance: are we on track for August 2026, is retention holding, is marketing working.</p>
        </div>
      </div>

      <div className="grid c4" style={{ marginBottom: 22 }}>
        <div className="kpi">
          <div className="lbl">Aug 2026 · Likely forecast</div>
          <div className="val">{F.scenarios.likely.total}<span className="unit">seats</span></div>
          <div className="foot">
            <span>{F.confirmed} confirmed today</span>
            <span className="delta neu">{Math.round(F.confirmed / F.scenarios.likely.total * 100)}% of target</span>
          </div>
          <div className="bar"><span style={{ width: (F.confirmed / F.scenarios.likely.total * 100) + "%" }} /></div>
        </div>

        <div className="kpi pressure">
          <div className="lbl">New enrolments needed</div>
          <div className="val">+{newNeeded}<span className="unit">to hit 254</span></div>
          <div className="foot">
            <span>{F.newConfirmed} confirmed · {F.yearLevels.reduce((a, y) => a + y.newPipeline, 0)} in pipeline</span>
          </div>
          <div className="bar"><span style={{ width: (F.newConfirmed / newNeeded * 100) + "%" }} /></div>
        </div>

        <div className="kpi accent-blue">
          <div className="lbl">Retention · applied out</div>
          <div className="val">{R.totalAppliedOut}<span className="unit">families</span></div>
          <div className="foot">
            <span>{R.confirmedLeaving} confirmed leaving</span>
            <span className="d-mini neu">vs 140 last yr</span>
          </div>
          <div className="bar"><span style={{ width: (R.confirmedLeaving / R.totalAppliedOut * 100) + "%", background: "var(--red)" }} /></div>
        </div>

        <div className="kpi accent-gold">
          <div className="lbl">Cost per enrolment</div>
          <div className="val">฿{(M.costPerEnrolment.current/1000).toFixed(1)}k</div>
          <div className="foot">
            <span>was ฿{(M.costPerEnrolment.trend[0].v/1000).toFixed(1)}k in Aug</span>
            <span className="d-mini pos">{cpeDrop}%</span>
          </div>
          <Sparkline data={M.costPerEnrolment.trend} accent="gold" />
        </div>
      </div>

      <div className="grid cs-2-1" style={{ marginBottom: 22 }}>
        <div className="card">
          <div className="card-head">
            <div>
              <h3>Aug 2026 scenarios · City School</h3>
              <div className="sub">Confirmed today: {F.confirmed}. Mel's working range for August.</div>
            </div>
            <span className="chip purple">Confidential · Leadership</span>
          </div>
          <ScenarioRange F={F} />
        </div>

        <div className="card">
          <h3>Retention this year</h3>
          <div className="sub">{R.asOf}</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginTop: 6 }}>
            <MiniStat label="Applied out" value={R.totalAppliedOut} delta="+4 vs LY" color="red" />
            <MiniStat label="Confirmed leaving" value={R.confirmedLeaving} delta={`−61 vs LY`} color="green" />
            <MiniStat label="Forced moves" value={R.forced} sub="relocation" color="neutral" />
            <MiniStat label="Unforced" value={R.unforcedLeaving} sub="chose other schools" color="orange" />
          </div>
          <div className="callout gold" style={{ marginTop: 14 }}>
            NIST pressure concentrated in Kindergarten: <b>K1 = 5</b> · <b>K2 = 16</b> accepted so far.
          </div>
        </div>
      </div>

      <div className="sec-hd"><h3>This month's narratives</h3><span className="sub">Three department heads · editable</span></div>
      <div className="grid c3">
        <Narrative k="admissions" author="Melissa Davison" role="Director of Admissions" color="purple" data={narratives.admissions} onChange={(t)=>setNarratives(n=>({...n,admissions:{...n.admissions,text:t}}))} editable={editable} />
        <Narrative k="retention"  author="Jem Wright" role="Head of Pastoral Care and Community" color="blue" data={narratives.retention} onChange={(t)=>setNarratives(n=>({...n,retention:{...n.retention,text:t}}))} editable={editable} />
        <Narrative k="marketing"  author="Federico Evangelista" role="Director of Comms & Experience" color="gold" data={narratives.marketing} onChange={(t)=>setNarratives(n=>({...n,marketing:{...n.marketing,text:t}}))} editable={editable} />
      </div>
    </div>
  );
}

function MiniStat({ label, value, delta, sub, color }) {
  return (
    <div style={{ background: "var(--surface)", border: "1px solid var(--hair)", borderRadius: 8, padding: "10px 12px" }}>
      <div style={{ fontSize: 10.5, letterSpacing: .6, textTransform: "uppercase", color: "var(--muted)", fontWeight: 600 }}>{label}</div>
      <div style={{ fontSize: 22, fontWeight: 600, letterSpacing: -.4, marginTop: 4, lineHeight: 1 }}>{value}</div>
      {delta && <div className={`d-mini ${color === "green" ? "pos" : color === "red" ? "neg" : "neu"}`} style={{ marginTop: 6 }}>{delta}</div>}
      {sub && <div style={{ fontSize: 11, color: "var(--muted)", marginTop: 6 }}>{sub}</div>}
    </div>
  );
}

// ─── Scenario range visual ───────────────────
function ScenarioRange({ F }) {
  const { worst, likely, best } = F.scenarios;
  const lo = 200, hi = 280;
  const pos = (v) => ((v - lo) / (hi - lo)) * 100;
  return (
    <div className="scen-wrap">
      <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, color: "var(--muted)", textTransform: "uppercase", letterSpacing: .5, marginBottom: 6 }}>
        <span>200</span><span>most-likely range</span><span>280</span>
      </div>
      <div className="scen-axis">
        <div className="scen-track" />
        <div className="scen-mark worst"   style={{ left: pos(worst.total) + "%" }}   data-label="Worst"><div className="v">{worst.total}</div></div>
        <div className="scen-mark likely"  style={{ left: pos(likely.total) + "%" }}  data-label="Likely"><div className="v">{likely.total}</div></div>
        <div className="scen-mark best"    style={{ left: pos(best.total) + "%" }}    data-label="Best"><div className="v">{best.total}</div></div>
        <div className="scen-mark current" style={{ left: pos(F.confirmed) + "%" }}   data-label="Today"><div className="v">{F.confirmed}</div></div>
      </div>
      <div className="legend" style={{ justifyContent: "space-around", marginTop: 18 }}>
        <div><b style={{ color: "var(--red)" }}>Worst</b> return {worst.return} + new {worst.new} + est {worst.returnEst}/{worst.newEst}</div>
        <div><b style={{ color: "var(--gold-dark)" }}>Likely</b> return {likely.return} + new {likely.new} + est {likely.returnEst}/{likely.newEst}</div>
        <div><b style={{ color: "var(--green)" }}>Best</b> return {best.return} + new {best.new} + est {best.returnEst}/{best.newEst}</div>
      </div>
    </div>
  );
}

// ─── Narrative card ──────────────────────────
function Narrative({ k, author, role, color, data, onChange, editable, compact }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(data.text);
  const words = draft.trim().split(/\s+/).filter(Boolean).length;
  useEffect(() => setDraft(data.text), [data.text]);

  const initials = author.split(" ").map(s => s[0]).slice(0, 2).join("");
  return (
    <div className="narr">
      <div className="narr-head">
        <div className="narr-who">
          <div className={`avatar ${color === "gold" ? "gold" : color === "blue" ? "blue" : ""}`}>{initials}</div>
          <div>
            <div className="n">{author}</div>
            <div className="r">{role}</div>
          </div>
        </div>
        {editable && !editing && <button className="btn sm ghost" onClick={() => setEditing(true)}>Edit</button>}
      </div>
      <div className="narr-text">
        {editing
          ? <textarea value={draft} onChange={(e) => setDraft(e.target.value)} placeholder="Write this month's 150-word update…" />
          : <p>{data.text}</p>}
      </div>
      <div className="narr-foot">
        <span>Last updated {data.lastUpdated} · {data.scope}</span>
        {editing ? (
          <span style={{ display: "flex", gap: 8, alignItems: "center" }}>
            <span className={`count ${words > 180 ? "over" : ""}`}>{words}/150 words</span>
            <button className="btn sm" onClick={() => { setDraft(data.text); setEditing(false); }}>Cancel</button>
            <button className="btn sm primary" onClick={() => { onChange(draft); setEditing(false); window.toast && window.toast("Narrative saved"); }}>Save</button>
          </span>
        ) : null}
      </div>
    </div>
  );
}

// ─── Admissions Forecast ─────────────────────
function ForecastView({ narratives, setNarratives, editable }) {
  const F = DATA.admissions.forecast;
  const ctx = F.contextVsLastYear;
  const totalAllYears = F.yearLevels.reduce((a, y) => ({
    stay: a.stay + y.confirmedStaying,
    newc: a.newc + y.newConfirmed,
    likely: a.likely + y.likelyUnsure,
    newp: a.newp + y.newPipeline,
    unlikely: a.unlikely + y.unlikelyUnsure,
  }), { stay: 0, newc: 0, likely: 0, newp: 0, unlikely: 0 });

  return (
    <div className="view">
      <div className="view-hd">
        <div>
          <h2>Admissions Forecast <span className="scope-tag">City School · Aug 2026</span></h2>
          <p>Scenario range, year-level stack, and this month's priorities. Data as of {F.asOf}. Purple Elephant and Dove Centre added in production.</p>
        </div>
        <div>
          <span className="chip purple">Confidential · Leadership</span>
        </div>
      </div>

      <div className="card" style={{ marginBottom: 16 }}>
        <div className="card-head">
          <div>
            <h3>Three-scenario range vs today</h3>
            <div className="sub">{F.confirmed} confirmed · {totalAllYears.newp} in pipeline · {F.yearLevels.reduce((a,y)=>a+y.likelyUnsure,0)} likely-unsure</div>
          </div>
        </div>
        <ScenarioRange F={F} />
      </div>

      <div className="grid cs-2-1">
        <div className="card">
          <div className="card-head">
            <div>
              <h3>Year-level forecast</h3>
              <div className="sub">Each bar totals to pipeline size. Y6 shown for completeness (not tracked as "applied out" by retention).</div>
            </div>
          </div>
          <div style={{ padding: "0 4px" }}>
            {F.yearLevels.map(y => {
              const total = y.confirmedStaying + y.newConfirmed + y.likelyUnsure + y.newPipeline + y.unlikelyUnsure;
              const confirmed = y.confirmedStaying + y.newConfirmed;
              return (
                <div className="fcst-row" key={y.year}>
                  <div className="yr">{y.year}</div>
                  <div className="fcst-bar" data-tt={`${y.year}: ${confirmed} confirmed · ${total} total pool`}>
                    <div className="fcst-seg stay"     style={{ flex: y.confirmedStaying }} />
                    <div className="fcst-seg newc"     style={{ flex: y.newConfirmed }} />
                    <div className="fcst-seg likely"   style={{ flex: y.likelyUnsure }} />
                    <div className="fcst-seg newp"     style={{ flex: y.newPipeline }} />
                    <div className="fcst-seg unlikely" style={{ flex: y.unlikelyUnsure }} />
                  </div>
                  <div className="total"><b>{confirmed}</b>/ {total}</div>
                </div>
              );
            })}
          </div>
          <div className="legend" style={{ marginTop: 14, justifyContent: "center" }}>
            <span className="sw stay">Confirmed staying</span>
            <span className="sw newc">New confirmed</span>
            <span className="sw likely">Likely unsure</span>
            <span className="sw newp">New pipeline</span>
            <span className="sw unlikely">Unlikely unsure</span>
          </div>
        </div>

        <div style={{ display: "grid", gap: 16 }}>
          <div className="card">
            <h3>Context vs last year</h3>
            <div className="sub">Same point in cycle</div>
            <div style={{ marginTop: 10 }}>
              <CompareRow label="Return-confirmed staying" a={ctx.returnConfirmedStayingThisYear} b={ctx.returnConfirmedStayingLastYear} note="Broadly in line" />
              <CompareRow label="Return-estimated staying" a={ctx.returnEstimatedStayingThisYear} b={ctx.returnEstimatedStayingLastYear} note="Smaller pool to convert" warn />
              <div className="callout" style={{ marginTop: 12 }}>
                Last year converted <b>{ctx.lastYearConversionRate}%</b> of the estimated-staying pool. Target: exceed that with structured outreach from Jem on the 61 likely-unsure.
              </div>
            </div>
          </div>

          <div className="card">
            <h3>Attrition benchmark</h3>
            <div className="sub">Protect the base</div>
            <div style={{ display: "flex", gap: 12, marginTop: 8 }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 26, fontWeight: 600, color: "var(--purple)", letterSpacing: -.4 }}>{F.attritionBenchmarks.typicalUnexpectedAttritionCitySchool}</div>
                <div style={{ fontSize: 11.5, color: "var(--muted)" }}>City School typical unexpected attrition (seats)</div>
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 26, fontWeight: 600, color: "var(--gold-dark)", letterSpacing: -.4 }}>{F.attritionBenchmarks.purpleElephantAttritionLastYear}</div>
                <div style={{ fontSize: 11.5, color: "var(--muted)" }}>Purple Elephant attrition last year (seats)</div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div className="sec-hd"><h3>This month's priorities</h3><span className="sub">From Mel</span></div>
      <div className="grid c3" style={{ marginBottom: 22 }}>
        {F.priorities.map((p, i) => (
          <div key={i} className={`pri-card ${p.urgency}`}>
            <div className="n">{i + 1}</div>
            <div className="body">
              <h4>{p.title}<span className="tgt">{p.target}</span></h4>
              <p>{p.action}</p>
            </div>
          </div>
        ))}
      </div>

      <div className="sec-hd"><h3>Admissions narrative</h3><span className="sub">Mel Davison · 150-word soft target</span></div>
      <Narrative k="admissions" author="Melissa Davison" role="Director of Admissions" color="purple" data={narratives.admissions} onChange={(t)=>setNarratives(n=>({...n,admissions:{...n.admissions,text:t}}))} editable={editable} />
    </div>
  );
}

function CompareRow({ label, a, b, note, warn }) {
  const diff = a - b;
  return (
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "10px 0", borderBottom: "1px solid var(--hair)" }}>
      <div>
        <div style={{ fontSize: 12.5, fontWeight: 600 }}>{label}</div>
        <div style={{ fontSize: 11.5, color: warn ? "var(--orange)" : "var(--muted)", marginTop: 2 }}>{note}</div>
      </div>
      <div style={{ textAlign: "right" }}>
        <div style={{ fontSize: 15, fontWeight: 600 }}>{a} <span style={{ color: "var(--muted)", fontWeight: 500, fontSize: 12 }}>vs {b}</span></div>
        <span className={`d-mini ${diff > 0 ? "pos" : diff < 0 ? "neg" : "neu"}`}>{diff > 0 ? "+" : ""}{diff}</span>
      </div>
    </div>
  );
}

Object.assign(window, { OverviewView, ForecastView, Narrative, ScenarioRange });
