/* educator-upload.jsx — Presentation Studio: upload PDF → convert to HTML deck → publish to learners */

function PresentationStudio({ toast, embedded, course, courseColor }) {
  const [stage, setStage]       = useState("idle");      // idle | converting | preview
  const [progress, setProgress] = useState(0);
  const [slides, setSlides]     = useState([]);          // [{img,w,h}]
  const [deckTitle, setTitle]   = useState("");
  const [fileName, setFileName] = useState("");
  const [published, setPub]     = useState([]);
  const [dragOver, setDrag]     = useState(false);
  const [busy, setBusy]         = useState(false);
  const [sections, setSections]  = useState([{title:'Full Deck', start:0}]);
  const [present, setPresent]    = useState(null);   // deck-like obj for HTML preview
  const [builder, setBuilder]    = useState(null);   // deck for Study Builder
  const [official, setOfficial]  = useState(false);  // shared IPMA-D master slideware overlay
  const fileRef = React.useRef(null);

  useEffect(() => { refresh(); }, []);
  async function refresh() {
    try {
      if (embedded && course && window.SeedDecks) await window.SeedDecks.ensureForCourse(course, courseColor);
      const d = await window.DeckStore.list(); setPub((d || []).filter(x => !embedded || (x.course || null) === (course || null)).sort((a, b) => b.created - a.created));
    } catch (e) {}
  }

  function pick() { fileRef.current && fileRef.current.click(); }

  function onDrop(e) {
    e.preventDefault(); setDrag(false);
    const f = e.dataTransfer.files && e.dataTransfer.files[0];
    if (f) handleFile(f);
  }

  function fileToDataURL(file) {
    return new Promise((res) => { const r = new FileReader(); r.onload = () => res(r.result); r.readAsDataURL(file); });
  }

  async function handleFile(file) {
    if (!file) return;
    setFileName(file.name);
    setTitle(file.name.replace(/\.(pdf|pptx?|key)$/i, "").replace(/[_-]+/g, " "));
    if (/\.pdf$/i.test(file.name)) {
      await convertPDF(file);
    } else if (/\.(png|jpe?g|webp)$/i.test(file.name)) {
      const url = await fileToDataURL(file);
      const dim = await imgDims(url);
      setSlides([{ img: url, w: dim.w, h: dim.h }]);
      setStage("preview");
    } else {
      toast("Upload a PDF — export your PowerPoint/Keynote to PDF first for best quality", "file");
    }
  }

  function imgDims(url) {
    return new Promise((res) => { const i = new Image(); i.onload = () => res({ w: i.naturalWidth, h: i.naturalHeight }); i.src = url; });
  }

  async function convertPDF(file) {
    if (!window.pdfjsLib) { toast("PDF engine still loading — try again in a moment", "refresh"); return; }
    setStage("converting"); setProgress(0); setSlides([]);
    try {
      const buf = await file.arrayBuffer();
      const pdf = await window.pdfjsLib.getDocument({ data: buf }).promise;
      const out = [];
      for (let i = 1; i <= pdf.numPages; i++) {
        const page = await pdf.getPage(i);
        const vp1 = page.getViewport({ scale: 1 });
        const scale = Math.min(2.2, 1920 / vp1.width);
        const vp = page.getViewport({ scale });
        const canvas = document.createElement("canvas");
        canvas.width = Math.round(vp.width); canvas.height = Math.round(vp.height);
        await page.render({ canvasContext: canvas.getContext("2d"), viewport: vp }).promise;
        out.push({ img: canvas.toDataURL("image/jpeg", 0.82), w: canvas.width, h: canvas.height });
        setProgress(Math.round((i / pdf.numPages) * 100));
        setSlides(out.slice());
      }
      setStage("preview");
      toast(`Converted ${out.length} slides in high quality`, "check");
    } catch (e) {
      toast("Conversion failed — " + (e.message || e), "x");
      setStage("idle");
    }
  }

  async function publish() {
    if (!slides.length || busy) return;
    setBusy(true);
    const groupTitle = deckTitle.trim() || "Untitled Presentation";
    const multi = sections.length > 1;
    const groupId = multi ? "grp_" + Date.now() : null;
    try {
      for (let si = 0; si < sections.length; si++) {
        const sec = sections[si];
        const end = sections[si + 1] ? sections[si + 1].start : slides.length;
        const secSlides = slides.slice(sec.start, end);
        await window.DeckStore.save({
          id: "deck_" + Date.now() + "_" + si,
          title: multi ? sec.title : groupTitle,
          group: groupId,
          groupTitle: multi ? groupTitle : null,
          part: multi ? si + 1 : null,
          totalParts: multi ? sections.length : null,
          slides: secSlides.map(s => s.img),
          ratio: secSlides[0] ? secSlides[0].w / secSlides[0].h : 16 / 9,
          created: Date.now() + si,
          gamified: false,
          course: course || null,
          source: fileName,
        });
      }
      toast(multi ? "Published " + sections.length + " sections ✓" : "Published to the learner environment ✓", "check");
      reset(); refresh();
    } catch (e) {
      toast("Publish failed — presentation may be too large", "x");
    }
    setBusy(false);
  }

  function reset() { setStage("idle"); setSlides([]); setTitle(""); setFileName(""); setProgress(0); setSections([{title:'Full Deck',start:0}]); }

  function autoSplit(size) {
    if (!size || size >= slides.length) { setSections([{title:'Full Deck', start:0}]); return; }
    const secs = [];
    for (let i = 0; i < slides.length; i += size) secs.push({ title: 'Day ' + (secs.length + 1), start: i });
    setSections(secs);
  }
  function removeSplit(idx) { setSections(p => p.length <= 1 ? p : p.filter((_, i) => i !== idx)); }
  function renameSec(idx, t) { setSections(p => p.map((s, i) => i === idx ? {...s, title:t} : s)); }
  function addSplitAt(slideIdx) {
    setSections(prev => {
      if (prev.some(s => s.start === slideIdx)) return prev;
      const next = [...prev, {title:'Section '+(prev.length+1), start:slideIdx}];
      next.sort((a,b) => a.start - b.start);
      return next;
    });
  }

  async function toggleGamify(deck) {
    deck.gamified = !deck.gamified;
    try { await window.DeckStore.save(deck); refresh(); toast(deck.gamified ? "Gamification enabled — quiz slides active" : "Gamification disabled", deck.gamified ? "bolt" : "toggle"); } catch (e) {}
  }

  async function del(id) { try { await window.DeckStore.remove(id); refresh(); toast("Deck removed", "check"); } catch (e) {} }

  function closeBuilder(saved) { setBuilder(null); if (saved) refresh(); }

  return (
    <div>
      <div className="between" style={{ marginBottom: embedded ? 16 : 24 }}>
        {embedded ? <div /> :
        <div className="page-head" style={{ marginBottom: 0 }}>
          <h1>Presentation Studio</h1>
          <p>Upload a presentation — we convert it to a high-quality HTML deck your learners can view and you can gamify.</p>
        </div>}
        {stage === "preview" && <button className="btn btn-ghost" onClick={reset}><Icon name="x" size={15} />Discard</button>}
      </div>

      {/* ── OFFICIAL MASTER SLIDEWARE (shared across Learner / Trainer / Educator) ── */}
      {embedded && course && /IPMA-?D/i.test(course) && window.IPMA_SL && (
        <div className="card" style={{ padding: 18, marginBottom: 18, display: "flex", alignItems: "center", gap: 16, background: "linear-gradient(135deg,#0c1830,#16335c)", border: "1px solid #1e3a5f" }}>
          <div style={{ width: 46, height: 46, borderRadius: 12, background: "var(--vh-orange)", display: "grid", placeItems: "center", flexShrink: 0 }}><Icon name="slides" size={22} style={{ color: "#231f20" }} /></div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 9, flexWrap: "wrap" }}>
              <div style={{ fontFamily: "var(--display)", fontWeight: 800, fontSize: 16.5, color: "#fff", whiteSpace: "nowrap" }}>Official IPMA-D® Slideware</div>
              <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 11, fontWeight: 700, color: "#f99d25", background: "rgba(249,157,37,.15)", border: "1px solid rgba(249,157,37,.3)", borderRadius: 999, padding: "3px 10px", whiteSpace: "nowrap" }}>● Synced · Learner · Trainer · Educator</span>
            </div>
            <div style={{ fontSize: 13, color: "rgba(200,216,240,.75)", marginTop: 7 }}>The {window.IPMA_SL.length}-slide master deck — the exact slides learners study and trainers present live. One source of truth.</div>
          </div>
          <button className="btn btn-acc" onClick={() => setOfficial(true)} style={{ flexShrink: 0 }}><Icon name="search" size={15} />View slideware</button>
        </div>
      )}

      {/* ── UPLOAD / CONVERT / PREVIEW ── */}
      {stage === "idle" && (
        <div className="card" onClick={pick} onDragOver={e => { e.preventDefault(); setDrag(true); }} onDragLeave={() => setDrag(false)} onDrop={onDrop}
          style={{ padding: "60px 40px", textAlign: "center", cursor: "pointer", border: "2px dashed " + (dragOver ? "var(--vh-blue-500)" : "var(--line)"), background: dragOver ? "var(--vh-blue-50)" : "var(--surface)", transition: "all .15s" }}>
          <div style={{ width: 72, height: 72, borderRadius: 20, background: "var(--vh-blue-50)", display: "grid", placeItems: "center", margin: "0 auto 20px" }}>
            <Icon name="download" size={32} style={{ color: "var(--vh-blue-500)", transform: "rotate(180deg)" }} />
          </div>
          <div style={{ fontFamily: "var(--display)", fontWeight: 800, fontSize: 22, color: "var(--ink)", marginBottom: 8 }}>Drop your presentation here</div>
          <p style={{ fontSize: 14.5, color: "var(--ink-2)", maxWidth: 460, margin: "0 auto 20px", lineHeight: 1.6 }}>
            Upload a <strong>PDF</strong> (export your PowerPoint, Keynote or Google Slides to PDF) and we'll rebuild it as a crisp, full-resolution HTML presentation — text, images and layout preserved.
          </p>
          <button className="btn btn-acc" onClick={e => { e.stopPropagation(); pick(); }}><Icon name="file" size={15} />Choose file</button>
          <input ref={fileRef} type="file" accept=".pdf,image/*" style={{ display: "none" }} onChange={e => handleFile(e.target.files[0])} />
          <div style={{ fontSize: 12.5, color: "var(--ink-3)", marginTop: 18 }}>PDF · PNG · JPG · any size — large decks are split into sections</div>
        </div>
      )}

      {stage === "converting" && (
        <div className="card" style={{ padding: "56px 40px", textAlign: "center" }}>
          <div style={{ fontFamily: "var(--display)", fontWeight: 800, fontSize: 20, color: "var(--ink)", marginBottom: 6 }}>Converting "{fileName}"…</div>
          <p style={{ fontSize: 14, color: "var(--ink-2)", marginBottom: 24 }}>Rendering each slide at high resolution</p>
          <div style={{ maxWidth: 420, margin: "0 auto" }}>
            <div className="bar" style={{ height: 10 }}><i style={{ width: progress + "%" }} /></div>
            <div style={{ fontFamily: "var(--display)", fontWeight: 800, fontSize: 28, color: "var(--vh-blue-500)", marginTop: 14 }}>{progress}%</div>
            <div style={{ fontSize: 13, color: "var(--ink-3)" }}>{slides.length} slides done</div>
          </div>
        </div>
      )}

      {stage === "preview" && (
        <div>
          {/* Header */}
          <div className="card" style={{ padding: 20, marginBottom: 18, display: "flex", gap: 16, alignItems: "center", flexWrap: "wrap" }}>
            <div style={{ flex: 1, minWidth: 220 }}>
              <label style={{ fontSize: 12, fontWeight: 700, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: ".06em", display: "block", marginBottom: 6 }}>Presentation title</label>
              <input value={deckTitle} onChange={e => setTitle(e.target.value)} placeholder="e.g. PRINCE2 Foundation"
                style={{ width: "100%", padding: "11px 14px", border: "1.5px solid var(--line)", borderRadius: 10, fontSize: 15, color: "var(--ink)", background: "var(--surface)", fontFamily: "var(--body)", outline: "none" }}
                onFocus={e => e.target.style.borderColor = "var(--vh-blue-200)"} onBlur={e => e.target.style.borderColor = "var(--line)"} />
            </div>
            {/* Auto-split controls */}
            <div style={{ display: "flex", flexDirection: "column", gap: 6, alignItems: "flex-start" }}>
              <label style={{ fontSize: 11, fontWeight: 700, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: ".06em" }}>Split into sections</label>
              <div style={{ display: "flex", gap: 5 }}>
                {[[0,"No split"],[15,"15/sec"],[20,"20/sec"],[25,"25/sec"]].map(([n,lbl]) => {
                  const active = (n === 0 && sections.length <= 1) || (n > 0 && sections.length > 1 && Math.abs((sections[1]||{start:slides.length}).start - n) < 3);
                  return <button key={n} onClick={() => autoSplit(n)} style={{ padding: "6px 12px", borderRadius: 8, fontSize: 12.5, fontWeight: 600, border: "1.5px solid " + (active ? "var(--vh-blue-500)" : "var(--line)"), background: active ? "var(--vh-blue-50)" : "var(--surface)", color: active ? "var(--vh-blue-500)" : "var(--ink-2)", cursor: "pointer", fontFamily: "var(--body)", transition: "all .15s" }}>{lbl}</button>;
                })}
              </div>
            </div>
            <div style={{ textAlign: "right" }}>
              <div style={{ fontFamily: "var(--display)", fontWeight: 800, fontSize: 28, color: "var(--ink)" }}>{slides.length}</div>
              <div style={{ fontSize: 12, color: "var(--ink-3)", fontWeight: 600 }}>{sections.length > 1 ? sections.length + " sections" : "slides ready"}</div>
            </div>
            <button className="btn btn-acc" disabled={busy} onClick={publish} style={{ alignSelf: "stretch", padding: "0 26px" }}>
              <Icon name="share" size={16} />{busy ? "Publishing…" : sections.length > 1 ? "Publish " + sections.length + " sections" : "Publish to learners"}<Tip text={sections.length > 1 ? "Publish each section as a separate deck — learners see them grouped together" : "Make this deck available to all learners in the Presentations view"}/>
            </button>
          </div>

          {/* Sections with slides */}
          {sections.map((sec, si) => {
            const nextIdx = sections[si + 1] ? sections[si + 1].start : slides.length;
            const secSlides = slides.slice(sec.start, nextIdx);
            return (
              <div key={si + "-" + sec.start} style={{ marginBottom: 20 }}>
                {/* Section divider + header */}
                {sections.length > 1 && (
                  <div style={{ display: "flex", gap: 12, alignItems: "center", marginBottom: 12, marginTop: si > 0 ? 8 : 0 }}>
                    {si > 0 && <div style={{ flex: 1, height: 1, background: "var(--vh-blue-200)" }}/>}
                    <div style={{ width: 32, height: 32, borderRadius: 9, background: "var(--vh-blue-500)", display: "grid", placeItems: "center", fontFamily: "var(--display)", fontWeight: 800, fontSize: 15, color: "#fff", flexShrink: 0 }}>{si + 1}</div>
                    <input value={sec.title} onChange={e => renameSec(si, e.target.value)}
                      style={{ padding: "7px 12px", border: "1.5px solid var(--line)", borderRadius: 8, fontSize: 14, fontWeight: 700, color: "var(--ink)", background: "var(--surface)", fontFamily: "var(--body)", outline: "none", width: 200 }}
                      onFocus={e => e.target.style.borderColor = "var(--vh-blue-200)"}
                      onBlur={e => e.target.style.borderColor = "var(--line)"} />
                    <span className="dim" style={{ fontSize: 12.5, fontWeight: 600 }}>{secSlides.length} slides (#{sec.start + 1}–{nextIdx})</span>
                    {si > 0 && <button onClick={() => removeSplit(si)} className="btn btn-ghost btn-sm" style={{ color: "var(--ink-3)" }}><Icon name="x" size={13}/>Remove</button>}
                    <div style={{ flex: 1, height: 1, background: "var(--vh-blue-200)" }}/>
                  </div>
                )}
                {/* Slide grid */}
                <div style={{ display: "grid", gridTemplateColumns: "repeat(5,1fr)", gap: 10 }}>
                  {secSlides.map((s, i) => {
                    const gIdx = sec.start + i;
                    return (
                      <div key={gIdx} style={{ position: "relative" }}>
                        <div className="card" style={{ padding: 0, overflow: "hidden", cursor: "pointer" }}
                          onClick={() => setPresent({ title: deckTitle || "Preview", slides: slides.map(x => x.img), ratio: (slides[0] ? slides[0].w / slides[0].h : 16/9), enhance: {}, _start: gIdx })}>
                          <div style={{ position: "relative", aspectRatio: (s.w / s.h) || (16 / 9), background: "#000" }}>
                            <img src={s.img} alt={"Slide " + (gIdx + 1)} style={{ width: "100%", height: "100%", objectFit: "contain", display: "block" }} />
                            <div style={{ position: "absolute", bottom: 4, right: 6, fontSize: 10, fontWeight: 700, color: "#fff", background: "rgba(0,0,0,.55)", borderRadius: 4, padding: "1px 6px" }}>{gIdx + 1}</div>
                            <div className="prev-ov" style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", background: "rgba(10,18,32,.4)", opacity: 0, transition: "opacity .15s" }}
                              onMouseEnter={e => e.currentTarget.style.opacity = 1} onMouseLeave={e => e.currentTarget.style.opacity = 0}>
                              <span style={{ display: "inline-flex", alignItems: "center", gap: 6, background: "rgba(255,255,255,.95)", color: "var(--vh-navy)", fontSize: 12, fontWeight: 700, padding: "6px 12px", borderRadius: 8 }}><Icon name="search" size={13} />Preview</span>
                            </div>
                          </div>
                        </div>
                        {/* Manual split button — show on last slide of section if not at end */}
                        {i === secSlides.length - 1 && gIdx < slides.length - 1 && sections.length <= 1 && (
                          <button onClick={() => addSplitAt(gIdx + 1)}
                            style={{ width: "100%", marginTop: 6, padding: "5px 0", borderRadius: 6, border: "1.5px dashed var(--line)", background: "none", color: "var(--ink-3)", fontSize: 11, fontWeight: 600, cursor: "pointer", fontFamily: "var(--body)", transition: "all .15s" }}
                            onMouseEnter={e => { e.currentTarget.style.borderColor = "var(--vh-blue-500)"; e.currentTarget.style.color = "var(--vh-blue-500)"; }}
                            onMouseLeave={e => { e.currentTarget.style.borderColor = "var(--line)"; e.currentTarget.style.color = "var(--ink-3)"; }}>
                            ✂ Split after slide {gIdx + 1}
                          </button>
                        )}
                      </div>
                    );
                  })}
                </div>
              </div>
            );
          })}
        </div>
      )}

      {/* ── PUBLISHED DECKS ── */}
      <div style={{ marginTop: embedded ? 24 : 36 }}>
        <div className="eyebrow" style={{ marginBottom: 14 }}>{embedded ? "Courseware decks · visible to this course's learners" : "Published presentations · visible to learners"}</div>
        {published.length === 0 ? (
          <div className="card" style={{ padding: "28px", textAlign: "center", color: "var(--ink-3)", fontSize: 14 }}>No presentations published yet. Upload one above to make it available in the learner environment.</div>
        ) : (
          <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 16 }}>
            {published.map(d => (
              <div key={d.id} className="card" style={{ padding: 0, overflow: "hidden" }}>
                <div style={{ aspectRatio: d.ratio || 16 / 9, background: "#000", position: "relative", cursor: "pointer" }}
                  onClick={() => setPresent(d)}>
                  <img src={d.slides[0]} alt={d.title} style={{ width: "100%", height: "100%", objectFit: "contain" }} />
                  {d.gamified && <span style={{ position: "absolute", top: 10, left: 10, display: "inline-flex", alignItems: "center", gap: 5, background: "rgba(249,157,37,.95)", color: "#231f20", fontSize: 11.5, fontWeight: 800, padding: "4px 10px", borderRadius: 999 }}><Icon name="bolt" size={12} />Gamified</span>}
                  <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", background: "rgba(10,18,32,.4)", opacity: 0, transition: "opacity .15s" }}
                    onMouseEnter={e => e.currentTarget.style.opacity = 1} onMouseLeave={e => e.currentTarget.style.opacity = 0}>
                    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, background: "rgba(255,255,255,.95)", color: "var(--vh-navy)", fontSize: 12.5, fontWeight: 700, padding: "7px 14px", borderRadius: 8 }}><Icon name="search" size={13} />Preview</span>
                  </div>
                </div>
                <div style={{ padding: "14px 16px" }}>
                  <div style={{ fontWeight: 700, fontSize: 15, color: "var(--ink)", marginBottom: 3, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{d.title}</div>
                  <div className="dim" style={{ fontSize: 12.5, marginBottom: 14 }}>{d.slides.length} slides · {new Date(d.created).toLocaleDateString("en-GB", { day: "numeric", month: "short" })}</div>
                  <div style={{ display: "flex", gap: 8 }}>
                    <button className="btn btn-acc btn-sm" style={{ flex: 1, justifyContent: "center" }} onClick={() => setBuilder(d)}>
                      <Icon name="wand" size={13} />Build study<Tip text="Walk the deck slide-by-slide to style or gamify individual slides"/>
                    </button>
                    <button className="btn btn-outline btn-sm" onClick={() => setPresent(d)} title="Preview in HTML display"><Icon name="search" size={13} /></button>
                    <button className="btn btn-outline btn-sm" onClick={() => del(d.id)} style={{ color: "#c62828" }}><Icon name="x" size={13} /></button>
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
      {present && <DeckPresent deck={present} enhance={present.enhance} startIdx={present._start || 0} onClose={() => setPresent(null)} />}
      {builder && <StudyBuilder deck={builder} toast={toast} onClose={closeBuilder} />}
      {official && window.IPMADeckOverlay && <window.IPMADeckOverlay onClose={() => setOfficial(false)} />}
    </div>
  );
}

Object.assign(window, { PresentationStudio });
