/* ============================================================
   Ripple Effect — app (React, in-browser Babel)
   Reads window.RIPPLE (engine). Mounts into #root.
   ============================================================ */
const { useState, useEffect, useMemo, useRef } = React;
const { EVENTS, FIELDS, DEFAULT_CTX, DEFAULT_MAGS, compute, inr } = window.RIPPLE;

const LS_KEY = 'ripple_state_v1';
const loadState = () => {
  try {
    const s = JSON.parse(localStorage.getItem(LS_KEY));
    if (s && s.ctx && s.mags) return s;
  } catch (e) {}
  return { step: 0, eventId: null, mags: { ...DEFAULT_MAGS }, ctx: { ...DEFAULT_CTX } };
};

/* ---------- small controls ---------- */
function Range({ value, min, max, step, onChange }) {
  const pct = ((value - min) / (max - min)) * 100;
  return (
    <input type="range" min={min} max={max} step={step} value={value}
      style={{ '--fill': pct + '%' }}
      onChange={(e) => onChange(parseFloat(e.target.value))} />
  );
}

function Stepper({ value, min, max, onChange }) {
  return (
    <div className="stepper">
      <button onClick={() => onChange(Math.max(min, value - 1))} aria-label="decrease">−</button>
      <span className="num">{value}</span>
      <button onClick={() => onChange(Math.min(max, value + 1))} aria-label="increase">+</button>
    </div>
  );
}

function Seg({ value, opts, labels, onChange }) {
  return (
    <div className="seg">
      {opts.map((o, i) => (
        <button key={o} className={value === o ? 'on' : ''} onClick={() => onChange(o)}>{labels[i]}</button>
      ))}
    </div>
  );
}

function Field({ fkey, ctx, setCtx }) {
  const f = FIELDS[fkey];
  if (!f) return null;
  const v = ctx[fkey];
  const set = (nv) => setCtx({ ...ctx, [fkey]: nv });
  const display = f.fmt ? f.fmt(v) : (v + (f.unit && f.unit !== '₹' ? ' ' + f.unit : ''));
  return (
    <div className="field">
      <div className="frow">
        <span className="flab">{f.label}</span>
        {f.type === 'stepper'
          ? <Stepper value={v} min={f.min} max={f.max} onChange={set} />
          : f.type === 'seg'
            ? <Seg value={v} opts={f.opts} labels={f.labels} onChange={set} />
            : <span className="fval"><b>{display}</b></span>}
      </div>
      {f.type === 'slider' && <Range value={v} min={f.min} max={f.max} step={f.step} onChange={set} />}
    </div>
  );
}

/* ---------- step 1: pick ---------- */
function StepPick({ eventId, onPick }) {
  return (
    <div className="step">
      <div className="eyebrow">Step 1</div>
      <h1 className="steptitle">What rocked your month?</h1>
      <p className="stepsub">Pick the headline. We'll translate it to your kitchen table.</p>
      <div className="egrid">
        {EVENTS.map((e) => (
          <button key={e.id} className={'etile' + (eventId === e.id ? ' sel' : '')} onClick={() => onPick(e.id)}>
            <span className="glyph">{e.glyph}</span>
            <span>
              <span className="en">{e.name}</span>
              <span className="eb" style={{ display: 'block', marginTop: '3px' }}>{e.blurb}</span>
            </span>
          </button>
        ))}
      </div>
    </div>
  );
}

/* ---------- step 2: tune ---------- */
function StepTune({ event, mags, setMags, ctx, setCtx, live }) {
  return (
    <div className="step">
      <div className="eyebrow">Step 2 · {event.name}</div>
      <h1 className="steptitle">Tune it to your life</h1>
      <p className="stepsub">Set how big the change is, then tell us a little about you.</p>

      <div className="magwrap">
        {event.mags.map((mg) => (
          <div className="magcard" key={mg.key}>
            <div className="maglabel">
              <span className="lab">{mg.label}</span>
              <span className="val">{mg.fmt(mags[mg.key])}</span>
            </div>
            <Range value={mags[mg.key]} min={mg.min} max={mg.max} step={mg.step}
              onChange={(v) => setMags({ ...mags, [mg.key]: v })} />
            <div className="magticks"><span>{mg.fmt(mg.min)}</span><span>{mg.fmt(mg.max)}</span></div>
          </div>
        ))}
      </div>

      <div className="hint">✦ Questions below adapt to "{event.name}"</div>

      <div className="card" style={{ marginTop: '12px' }}>
        <div className="fieldlist">
          {event.fields.map((fk) => <Field key={fk} fkey={fk} ctx={ctx} setCtx={setCtx} />)}
        </div>
      </div>

      <div className="card" style={{ marginTop: '12px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <span className="stepsub" style={{ fontSize: '13px' }}>Running impact</span>
        <span style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '24px', color: 'var(--accent)', whiteSpace: 'nowrap' }}>{inr(live.money)}<span style={{ fontSize: '13px', color: 'var(--ink-3)', fontWeight: 400 }}>&nbsp;/mo</span></span>
      </div>
    </div>
  );
}

/* ---------- step 3: result ---------- */
function MoneyMath({ parts, total }) {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button className="mathbtn" onClick={() => setOpen(!open)}>{open ? '▾ hide the math' : '▸ how is this calculated?'}</button>
      {open && (
        <div className="math">
          {parts.map((p, i) => (
            <div className="ml" key={i}><span>{p.label}</span><span className="v">{inr(p.val)}</span></div>
          ))}
          <div className="ml tot"><span>Monthly impact</span><span className="v">{inr(total)}</span></div>
        </div>
      )}
    </>
  );
}

function StepResult({ result, onReset }) {
  const { event, money, days, pct, ripples, equivalents, parts } = result;
  const barPct = Math.min(100, pct * 100);
  return (
    <div className="step">
      <div className="hero">
        <span className="evchip">{event.glyph} {event.name} · {event.blurb}</span>
        <div className="label">Extra burden this month</div>
        <div className="big">{inr(money)}</div>
        <div className="days">= <b>{days.toFixed(1)} days</b> of your salary, gone</div>
        <div className="incbar">
          <div className="track"><i style={{ width: barPct + '%' }}></i></div>
          <div className="cap">{(pct * 100).toFixed(1)}% of your monthly income</div>
        </div>
        <div className="equiv">
          {equivalents.map((e, i) => (
            <div className="e" key={i}><div className="n">{e.n.toLocaleString('en-IN')}</div><div className="l">{e.label}</div></div>
          ))}
        </div>
      </div>

      <div className="ripblock">
        <div className="rhead"><span className="t">How it ripples out</span><span className="c">5 dimensions</span></div>
        {ripples.map((r, i) => (
          <div className="ripple" data-sev={r.severity} key={i}>
            <div className="ic">{r.glyph}</div>
            <div className="rb">
              <div className="rtop"><span className="dim">{r.dim}</span><span className="delta">{r.delta}</span></div>
              <div className="why">{r.why}</div>
              <span className="sevtag">{r.severity === 'mod' ? 'Moderate' : r.severity} severity</span>
              {r.dim === 'Money' && <MoneyMath parts={parts} total={money} />}
            </div>
          </div>
        ))}
      </div>

      <div className="startover">Different scenario? <button onClick={onReset}>Start over</button></div>
    </div>
  );
}

/* ---------- share sheet ---------- */
function ShareSheet({ result, onClose, toast }) {
  const { event, money, days, equivalents } = result;
  const cardRef = useRef(null);
  const caption = `${event.glyph} ${event.name} is quietly eating ${inr(money)} — about ${days.toFixed(1)} days of my salary this month. Checked mine on Ripple Effect: https://maniac-tech.com/ripple-effect`;
  const doCopy = () => { try { navigator.clipboard.writeText(caption); } catch (e) {} toast('Caption copied'); };
  const doWA = () => { window.open('https://wa.me/?text=' + encodeURIComponent(caption), '_blank'); };
  const doSaveImage = () => {
    if (!cardRef.current || !window.html2canvas) return;
    window.html2canvas(cardRef.current, { backgroundColor: null, scale: 2 }).then((canvas) => {
      canvas.toBlob((blob) => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `ripple-effect-${event.id}.png`;
        a.click();
        URL.revokeObjectURL(url);
        toast('Image saved');
      }, 'image/png');
    });
  };
  return (
    <div className="sheet-scrim" onClick={onClose}>
      <div className="sheet" onClick={(e) => e.stopPropagation()}>
        <div className="grip"></div>
        <h3>Share your ripple</h3>
        <div className="sharecard" ref={cardRef}>
          <div className="ev">{event.glyph} {event.name}</div>
          <div className="big">{inr(money)}</div>
          <div className="sub">= {days.toFixed(1)} days of my salary, gone</div>
          <div className="row">
            {equivalents.map((e, i) => (
              <div className="s" key={i}><b>{e.n.toLocaleString('en-IN')}</b>{e.label}</div>
            ))}
          </div>
          <div className="mark">— <b>Ripple</b> Effect</div>
        </div>
        <div className="sharebtns">
          <button onClick={doWA}><span className="gl">💬</span>WhatsApp</button>
          <button onClick={doSaveImage}><span className="gl">⬇️</span>Save image</button>
          <button onClick={doCopy}><span className="gl">🔗</span>Copy text</button>
        </div>
        <div className="caption">"{caption}"</div>
        <button className="closebtn" onClick={onClose}>Close</button>
      </div>
    </div>
  );
}

/* ---------- app ---------- */
function App() {
  const [st, setSt] = useState(loadState);
  const [share, setShare] = useState(false);
  const [toastMsg, setToastMsg] = useState(null);
  const bodyRef = useRef(null);

  useEffect(() => { localStorage.setItem(LS_KEY, JSON.stringify(st)); }, [st]);
  useEffect(() => { if (bodyRef.current) bodyRef.current.scrollTop = 0; }, [st.step]);

  const toast = (m) => { setToastMsg(m); setTimeout(() => setToastMsg(null), 1600); };
  const event = st.eventId ? EVENTS.find((e) => e.id === st.eventId) : null;
  const result = useMemo(() => (event ? compute(event.id, st.mags, st.ctx) : null), [event, st.mags, st.ctx]);

  const setStep = (n) => setSt((s) => ({ ...s, step: n }));
  const pick = (id) => setSt((s) => ({ ...s, eventId: id }));
  const setMags = (m) => setSt((s) => ({ ...s, mags: m }));
  const setCtx = (c) => setSt((s) => ({ ...s, ctx: c }));
  const reset = () => setSt({ step: 0, eventId: null, mags: { ...DEFAULT_MAGS }, ctx: { ...DEFAULT_CTX } });

  const stepNames = ['Pick', 'Tune', 'Ripple'];
  return (
    <div className="app">
      <div className="appbar">
        <div className="brandline">
          <a href="/ripple-effect/" className="logomark" aria-label="Home" style={{ textDecoration: 'none' }}></a>
          <a href="/ripple-effect/" className="brandname" style={{ textDecoration: 'none' }}><b>Ripple</b> Effect</a>
          <span className="stepmeta">Step {st.step + 1} of 3 · {stepNames[st.step]}</span>
        </div>
        <div className="progress">
          {[0, 1, 2].map((i) => (
            <div key={i} className={'seg' + (i < st.step ? ' done' : i === st.step ? ' active' : '')}><i></i></div>
          ))}
        </div>
      </div>

      <div className="body" ref={bodyRef}>
        {st.step === 0 && <StepPick eventId={st.eventId} onPick={pick} />}
        {st.step === 1 && event && <StepTune event={event} mags={st.mags} setMags={setMags} ctx={st.ctx} setCtx={setCtx} live={result} />}
        {st.step === 2 && result && <StepResult result={result} onReset={reset} />}
      </div>

      <div className="footer">
        {st.step > 0 && <button className="btn btn-ghost" onClick={() => setStep(st.step - 1)}>Back</button>}
        {st.step === 0 && <button className="btn btn-primary" disabled={!st.eventId} onClick={() => setStep(1)}>{st.eventId ? 'Next →' : 'Pick an event'}</button>}
        {st.step === 1 && <button className="btn btn-primary" onClick={() => setStep(2)}>See the ripple →</button>}
        {st.step === 2 && <button className="btn btn-primary" onClick={() => setShare(true)}>Share this ↗</button>}
      </div>

      {share && result && <ShareSheet result={result} onClose={() => setShare(false)} toast={toast} />}
      {toastMsg && <div className="toast">{toastMsg}</div>}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
