/* Veridyne Learning Portal — gamification: XP, levels, toasts, level-up, share card */

function SidebarXp() {
  const store = useStore();
  const lvl = levelFor(store.xp.total);
  return (
    <div className="glass-inset" style={{ padding: "12px 14px", marginTop: 10 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, marginBottom: 7 }}>
        <span style={{ fontWeight: 600, fontSize: "0.85em", color: "var(--ember-bright)" }}>
          Level {lvl.idx + 1} · {lvl.name}
        </span>
        <span style={{ fontFamily: "var(--font-mono)", fontSize: "0.72em", color: "var(--bone-50)" }}>{store.xp.total} XP</span>
      </div>
      <div style={{ height: 7, borderRadius: 99, background: "var(--bone-12)", overflow: "hidden", marginBottom: 6 }}>
        <div style={{ height: "100%", borderRadius: 99, width: Math.round(lvl.progress * 100) + "%", background: "linear-gradient(90deg, var(--ember), var(--ember-bright))", transition: "width 0.5s ease" }} />
      </div>
      <div style={{ fontSize: "0.7em", color: "var(--bone-50)" }}>
        {lvl.next ? `${lvl.next.min - store.xp.total} XP to ${lvl.next.name}` : "Top level reached"}
      </div>
    </div>
  );
}

function MobileXpChip() {
  const store = useStore();
  const lvl = levelFor(store.xp.total);
  return (
    <button className="badge badge-ember" onClick={() => navigate("progress")}
      style={{ cursor: "pointer", padding: "5px 11px", fontSize: "0.72em" }}
      aria-label={`Level ${lvl.idx + 1}, ${store.xp.total} XP — open progress`}>
      <Icon name="zap" size={11} /> Lv {lvl.idx + 1} · {store.xp.total} XP
    </button>
  );
}

/* ---------------- Toasts + level-up ---------------- */
function XpToast({ toast, onDone }) {
  React.useEffect(() => {
    const t = setTimeout(() => onDone(toast.id), 2800);
    return () => clearTimeout(t);
  }, [toast.id]);
  return (
    <div className="xp-toast">
      <span className="xp-toast-amount">+{toast.amount} XP</span>
      <span style={{ fontSize: "0.85em", color: "var(--bone-70)" }}>{toast.reason}</span>
    </div>
  );
}

function LevelUpOverlay({ level, onClose }) {
  React.useEffect(() => {
    const t = setTimeout(onClose, 6500);
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => { clearTimeout(t); window.removeEventListener("keydown", onKey); };
  }, []);
  return (
    <div className="levelup-backdrop" onClick={onClose} role="dialog" aria-label="Level up">
      <div className="glass-raised levelup-card anim-fade-up" onClick={(e) => e.stopPropagation()}>
        <div className="levelup-ring">
          <VeridyneMark size={56} />
        </div>
        <p style={{ fontSize: "0.78em", letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--ember-bright)", fontWeight: 600, marginTop: 18 }}>Level up</p>
        <h2 style={{ fontSize: "1.7em", margin: "6px 0 4px" }}>{level.name}</h2>
        <p style={{ color: "var(--bone-70)", fontSize: "0.9em", marginBottom: 20 }}>Level {level.idx + 1} of {LEVELS.length} on the Veridyne track</p>
        <button className="btn btn-primary" onClick={onClose}>Keep going</button>
      </div>
    </div>
  );
}

function XpFeedback() {
  const store = useStore();
  return (
    <React.Fragment>
      <div className="xp-toasts" aria-live="polite">
        {store.toasts.map((t) => <XpToast key={t.id} toast={t} onDone={store.dismissToast} />)}
      </div>
      {store.levelUp ? <LevelUpOverlay level={store.levelUp} onClose={store.clearLevelUp} /> : null}
    </React.Fragment>
  );
}

/* ---------------- Share card ---------------- */
function buildShareStats(store) {
  const okta = trackProgress(store.completed, "okta-");
  const auth0 = trackProgress(store.completed, "auth0-");
  const lvl = levelFor(store.xp.total);
  const qs = (id) => {
    const s = store.scores[id];
    return s ? `${s.best}% (${scoreBadge(s.best).label})` : "not attempted";
  };
  return { okta, auth0, lvl, total: store.xp.total, oktaQuiz: qs("okta"), auth0Quiz: qs("auth0") };
}

function barText(done, total) {
  const filled = Math.round((done / total) * 10);
  return "▰".repeat(filled) + "▱".repeat(10 - filled);
}

function buildShareText(st) {
  return [
    "Veridyne Learning Portal",
    `Level ${st.lvl.idx + 1} — ${st.lvl.name} · ${st.total} XP`,
    `Okta track   ${barText(st.okta.done, st.okta.total)} ${st.okta.done}/${st.okta.total} modules`,
    `Auth0 track  ${barText(st.auth0.done, st.auth0.total)} ${st.auth0.done}/${st.auth0.total} modules`,
    `Okta quiz best: ${st.oktaQuiz} · Auth0 quiz best: ${st.auth0Quiz}`,
  ].join("\n");
}

function drawShareCard(canvas, st, markImg) {
  const W = 840, H = 440;
  canvas.width = W; canvas.height = H;
  const ctx = canvas.getContext("2d");
  const g = ctx.createLinearGradient(0, 0, W, H);
  g.addColorStop(0, "#1d2832"); g.addColorStop(1, "#10171d");
  ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
  const glow = ctx.createRadialGradient(W - 100, 30, 10, W - 100, 30, 360);
  glow.addColorStop(0, "rgba(180,99,42,0.28)"); glow.addColorStop(1, "rgba(180,99,42,0)");
  ctx.fillStyle = glow; ctx.fillRect(0, 0, W, H);

  if (markImg) ctx.drawImage(markImg, 44, 40, 68, 68);
  ctx.fillStyle = "#e5ddd0";
  ctx.font = "600 28px Outfit, Helvetica, sans-serif";
  ctx.fillText("Veridyne Learning Portal", 130, 72);
  ctx.fillStyle = "rgba(229,221,208,0.55)";
  ctx.font = "14px Outfit, Helvetica, sans-serif";
  ctx.fillText("Identity learning for Okta & Auth0 delivery teams", 130, 96);

  ctx.fillStyle = "#d07e3f";
  ctx.font = "600 22px Outfit, Helvetica, sans-serif";
  ctx.fillText(`Level ${st.lvl.idx + 1} — ${st.lvl.name}`, 44, 158);
  ctx.fillStyle = "rgba(229,221,208,0.7)";
  ctx.font = "500 16px 'IBM Plex Mono', monospace";
  ctx.fillText(`${st.total} XP`, 44, 184);

  const bar = (y, label, done, total, color) => {
    ctx.fillStyle = "#e5ddd0";
    ctx.font = "500 16px Outfit, Helvetica, sans-serif";
    ctx.fillText(label, 44, y);
    ctx.fillStyle = "rgba(229,221,208,0.55)";
    ctx.font = "13px Outfit, Helvetica, sans-serif";
    ctx.textAlign = "right";
    ctx.fillText(`${done}/${total} modules`, W - 44, y);
    ctx.textAlign = "left";
    const bw = W - 88, bh = 10, by = y + 12;
    ctx.fillStyle = "rgba(229,221,208,0.12)";
    ctx.beginPath(); ctx.roundRect(44, by, bw, bh, 5); ctx.fill();
    if (done > 0) {
      ctx.fillStyle = color;
      ctx.beginPath(); ctx.roundRect(44, by, Math.max(bh, bw * (done / total)), bh, 5); ctx.fill();
    }
  };
  bar(232, "Okta track", st.okta.done, st.okta.total, "#7da3cc");
  bar(296, "Auth0 track", st.auth0.done, st.auth0.total, "#d09a66");

  ctx.fillStyle = "rgba(229,221,208,0.8)";
  ctx.font = "15px Outfit, Helvetica, sans-serif";
  ctx.fillText(`Okta quiz best: ${st.oktaQuiz}    ·    Auth0 quiz best: ${st.auth0Quiz}`, 44, 366);

  ctx.fillStyle = "rgba(229,221,208,0.35)";
  ctx.font = "12px 'IBM Plex Mono', monospace";
  ctx.fillText("veridyne · internal learning portal", 44, 408);
}

function ShareCardModal({ open, onClose }) {
  const store = useStore();
  const canvasRef = React.useRef(null);
  const [copied, setCopied] = React.useState(false);
  const st = buildShareStats(store);

  React.useEffect(() => {
    if (!open || !canvasRef.current) return;
    const img = new Image();
    img.onload = () => drawShareCard(canvasRef.current, st, img);
    img.onerror = () => drawShareCard(canvasRef.current, st, null);
    img.src = "assets/veridyne-mark.png";
  }, [open, store.xp.total, store.completed.length, store.scores]);

  if (!open) return null;

  const copyText = () => {
    const text = buildShareText(st);
    const fallback = () => {
      const ta = document.createElement("textarea");
      ta.value = text; document.body.appendChild(ta);
      ta.select(); document.execCommand("copy"); ta.remove();
      setCopied(true); setTimeout(() => setCopied(false), 2000);
    };
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(text).then(() => {
        setCopied(true); setTimeout(() => setCopied(false), 2000);
      }).catch(fallback);
    } else fallback();
  };

  const downloadPng = () => {
    const a = document.createElement("a");
    a.href = canvasRef.current.toDataURL("image/png");
    a.download = "veridyne-progress.png";
    a.click();
  };

  return (
    <div className="sheet-backdrop anim-fade-in" onClick={onClose} style={{ alignItems: "center" }} role="dialog" aria-label="Share score card">
      <div className="glass-raised anim-fade-up" onClick={(e) => e.stopPropagation()}
        style={{ width: "min(560px, calc(100% - 24px))", padding: 22, margin: 12 }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
          <h3 style={{ fontSize: "1.05em" }}>Share your score card</h3>
          <button className="btn btn-ghost btn-sm" onClick={onClose} aria-label="Close"><Icon name="x" size={17} /></button>
        </div>
        <canvas ref={canvasRef} style={{ width: "100%", height: "auto", borderRadius: 14, border: "1px solid var(--glass-border)", display: "block", marginBottom: 14 }} />
        <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
          <button className="btn btn-primary" onClick={downloadPng}><Icon name="fileText" size={14} /> Download PNG</button>
          <button className="btn" onClick={copyText}>
            <Icon name={copied ? "check" : "list"} size={14} /> {copied ? "Copied!" : "Copy as text"}
          </button>
        </div>
        <p style={{ fontSize: "0.76em", color: "var(--bone-50)", marginTop: 12 }}>
          Paste the text version straight into Slack, or drop the image anywhere.
        </p>
      </div>
    </div>
  );
}

Object.assign(window, { SidebarXp, MobileXpChip, XpFeedback, ShareCardModal });
