/* ────────────────────────────────────────────────────────────
   share-view.jsx — 게스트 공유 뷰(feature b §6) — /share/<token> 에서 서빙
   브랜디드 헤더 + 읽기 전용(또는 코멘트 전용) 슬라이드 뷰. 편집 크롬 없음.
   · 부트스트랩: GET /api/share/:token (경로 토큰) — /auth/me 아님.
   · scope=comment 게스트는 루트 코멘트만 추가(이름 필드 필수, M5).
   · 404/만료/빈 상태 모두 비-백지(ErrorBoundary + 자체 폴백).
   REST: GET /api/share/:token · /:token/slides · /:token/comments · POST /:token/comments.
   window 노출 패턴. tokens·해요체·이모지 없음.
   ──────────────────────────────────────────────────────────── */

/* 경로에서 토큰 추출 — /share/<token>[/...] → <token>. */
function parseShareToken() {
  try {
    const m = window.location.pathname.match(/^\/share\/([^/?#]+)/);
    return m ? decodeURIComponent(m[1]) : null;
  } catch (e) { return null; }
}

/* 게스트 코멘트 작성 박스 — 이름(필수) + 본문. 루트 코멘트만(답글 불가). */
function GuestCommentComposer({ slideId, token, onPosted }) {
  const [name, setName] = useState("");
  const [body, setBody] = useState("");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");

  const submit = useCallback(async () => {
    const nm = name.trim(), bd = body.trim();
    if (!nm) { setErr("이름을 입력해 주세요."); return; }
    if (!bd) { setErr("내용을 입력해 주세요."); return; }
    setBusy(true); setErr("");
    try {
      const data = await api(`/share/${token}/comments`, {
        method: "POST",
        body: { guestName: nm, slideId: slideId || undefined, body: bd },
      });
      setBody("");
      if (onPosted && data && data.comment) onPosted(data.comment);
    } catch (ex) {
      setErr(ex.message || "코멘트를 남기지 못했어요.");
    } finally { setBusy(false); }
  }, [name, body, slideId, token, onPosted]);

  return React.createElement("div", { style: { background: "var(--bg-normal)", border: "1px solid var(--border)", borderRadius: "var(--r-md)", padding: "13px 14px" } },
    React.createElement("div", { className: "t-label-2", style: { color: "var(--label-neutral)", fontWeight: 800, marginBottom: 9 } }, "코멘트 남기기"),
    React.createElement("input", {
      type: "text", value: name, onChange: (e) => setName(e.target.value), placeholder: "이름",
      style: { width: "100%", boxSizing: "border-box", height: 36, padding: "0 11px", marginBottom: 8, borderRadius: "var(--r-sm)", border: "1px solid var(--border)", background: "var(--bg-canvas)", color: "var(--label-normal)", fontSize: 13.5 },
    }),
    React.createElement("textarea", {
      value: body, onChange: (e) => setBody(e.target.value), rows: 3, placeholder: "이 슬라이드에 대한 의견을 적어 주세요.",
      style: { width: "100%", boxSizing: "border-box", resize: "vertical", padding: "9px 11px", borderRadius: "var(--r-sm)", border: "1px solid var(--border)", background: "var(--bg-canvas)", color: "var(--label-normal)", fontSize: 13.5, lineHeight: 1.5, fontFamily: "inherit" },
    }),
    err ? React.createElement("div", { className: "t-caption-1", style: { color: "var(--negative)", marginTop: 6 } }, err) : null,
    React.createElement("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 9 } },
      React.createElement(Button, { kind: "primary", size: "sm", onClick: submit, disabled: busy },
        busy ? React.createElement(Spinner, { s: 14, color: "#fff" }) : "코멘트 등록")));
}

/* 게스트 코멘트 목록(현재 슬라이드) — 읽기. 작성자 이름 표시(이메일 없음). */
function GuestCommentList({ comments }) {
  if (!Array.isArray(comments) || comments.length === 0) {
    return React.createElement("div", { className: "t-caption-1", style: { color: "var(--label-assist)", padding: "8px 2px" } }, "아직 코멘트가 없어요.");
  }
  return React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 8 } },
    comments.map((c) => {
      const who = (c.author && c.author.name) || c.guestName || "게스트";
      return React.createElement("div", { key: c.commentId, style: { background: "var(--bg-normal)", border: "1px solid var(--border)", borderRadius: "var(--r-sm)", padding: "10px 12px" } },
        React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 4 } },
          React.createElement("span", { className: "t-caption-1", style: { fontWeight: 800, color: "var(--label-normal)" } }, who),
          c.guestName && !(c.author && c.author.name) ? React.createElement(Pill, { color: "var(--label-alt)", bg: "var(--bg-alt)" }, "게스트") : null),
        React.createElement("div", { className: "t-caption-1", style: { color: "var(--label-neutral)", lineHeight: 1.55, whiteSpace: "pre-wrap", wordBreak: "break-word" } }, c.body));
    }));
}

/* ── ShareView — 전체 게스트 페이지 ── */
function ShareView() {
  const token = useMemo(() => parseShareToken(), []);
  const [meta, setMeta] = useState(null);       // { project, scope, guestNameRequired } | null
  const [slides, setSlides] = useState(null);   // normSlide[] | null
  const [comments, setComments] = useState([]);
  const [idx, setIdx] = useState(0);
  const [status, setStatus] = useState("loading");   // loading | ok | notfound | error
  const [errMsg, setErrMsg] = useState("");

  const slide = (slides && slides[idx]) || null;
  const canComment = meta && meta.scope === "comment";

  /* 부트스트랩 — 메타 + 슬라이드. */
  useEffect(() => {
    let alive = true;
    (async () => {
      if (!token) { setStatus("notfound"); return; }
      try {
        const m = await api(`/share/${token}`);
        if (!alive) return;
        setMeta(m);
        const sd = await api(`/share/${token}/slides`);
        if (!alive) return;
        const norm = Array.isArray(sd?.slides) ? sd.slides.map(normSlide) : [];
        setSlides(norm);
        setStatus("ok");
      } catch (ex) {
        if (!alive) return;
        if (ex.status === 404) { setStatus("notfound"); }
        else { setErrMsg(ex.message || "공유 페이지를 불러오지 못했어요."); setStatus("error"); }
      }
    })();
    return () => { alive = false; };
  }, [token]);

  /* 현재 슬라이드 코멘트 로드. */
  const loadComments = useCallback(async () => {
    if (!token || !slide || !slide.slideId) { setComments([]); return; }
    try {
      const data = await api(`/share/${token}/comments?slideId=${encodeURIComponent(slide.slideId)}`);
      setComments(Array.isArray(data?.items) ? data.items : []);
    } catch (e) { setComments([]); }
  }, [token, slide]);
  useEffect(() => { loadComments(); }, [loadComments]);

  /* 브랜디드 헤더(모든 상태 공통). */
  const header = (sub) => React.createElement("header", {
    style: { borderBottom: "1px solid var(--border)", background: "var(--bg-normal)", padding: "14px 20px" },
  },
    React.createElement("div", { style: { maxWidth: 1080, margin: "0 auto", display: "flex", alignItems: "center", gap: 11 } },
      React.createElement("span", { style: { width: 30, height: 30, borderRadius: "var(--r-sm)", background: "var(--primary)", display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0 } },
        React.createElement("svg", { width: 17, height: 17, viewBox: "0 0 24 24", fill: "none", stroke: "#fff", strokeWidth: 2 }, React.createElement("rect", { x: 3, y: 3, width: 18, height: 18, rx: 2 }), React.createElement("path", { d: "M3 9h18M9 21V9" }))),
      React.createElement("div", { style: { minWidth: 0 } },
        React.createElement("div", { className: "t-label-1", style: { color: "var(--label-normal)", fontWeight: 800, lineHeight: 1.25, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, "Storyboard"),
        sub ? React.createElement("div", { className: "t-caption-1", style: { color: "var(--label-alt)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, sub) : null),
      React.createElement("div", { style: { marginLeft: "auto", flexShrink: 0 } },
        canComment
          ? React.createElement(Pill, { color: "var(--primary)", bg: "var(--primary-light)" }, "코멘트 가능")
          : React.createElement(Pill, { color: "var(--label-neutral)", bg: "var(--bg-alt)" }, "읽기 전용"))));

  /* 상태별 렌더 — 모두 헤더 + 본문. 절대 백지 없음. */
  if (status === "loading") {
    return React.createElement("div", { style: { minHeight: "100vh", background: "var(--bg-canvas)" } },
      header("공유 받은 스토리보드"),
      React.createElement(StateMsg, { icon: React.createElement(Spinner, { s: 24 }), title: "불러오는 중이에요" }));
  }
  if (status === "notfound") {
    return React.createElement("div", { style: { minHeight: "100vh", background: "var(--bg-canvas)" } },
      header("공유 링크"),
      React.createElement(StateMsg, {
        title: "링크를 찾을 수 없어요",
        desc: "공유 링크가 만료됐거나 해제됐을 수 있어요. 링크를 보낸 분에게 다시 요청해 주세요.",
      }));
  }
  if (status === "error") {
    return React.createElement("div", { style: { minHeight: "100vh", background: "var(--bg-canvas)" } },
      header("공유 링크"),
      React.createElement(StateMsg, {
        title: "불러오지 못했어요",
        desc: errMsg || "잠시 후 다시 시도해 주세요.",
        action: React.createElement(Button, { kind: "primary", onClick: () => location.reload() }, "새로고침"),
      }));
  }

  /* ok — 메타/슬라이드 표시. */
  const proj = (meta && meta.project) || {};
  const sub = [proj.courseName, proj.chapterName].filter(Boolean).join(" · ") || "공유 받은 스토리보드";

  return React.createElement("div", { style: { minHeight: "100vh", background: "var(--bg-canvas)", display: "flex", flexDirection: "column" } },
    header(sub),
    React.createElement("main", { style: { flex: 1, maxWidth: 1080, width: "100%", margin: "0 auto", padding: "22px 20px 48px", boxSizing: "border-box" } },
      (!slides || slides.length === 0)
        ? React.createElement(StateMsg, { title: "표시할 슬라이드가 없어요", desc: "아직 슬라이드가 만들어지지 않았어요." })
        : React.createElement("div", { style: { display: "grid", gridTemplateColumns: canComment ? "minmax(0,1fr) 320px" : "minmax(0,1fr)", gap: 22, alignItems: "start" } },
            /* 좌: 슬라이드 + 네비 */
            React.createElement("div", null,
              React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10, marginBottom: 12 } },
                React.createElement("span", { className: "t-label-1 tnum", style: { color: "var(--label-neutral)", fontWeight: 800 } }, `${idx + 1} / ${slides.length}`),
                React.createElement("div", { style: { marginLeft: "auto", display: "flex", gap: 6 } },
                  React.createElement(Button, { kind: "outline", size: "sm", disabled: idx <= 0, onClick: () => setIdx((i) => Math.max(0, i - 1)) }, "이전"),
                  React.createElement(Button, { kind: "outline", size: "sm", disabled: idx >= slides.length - 1, onClick: () => setIdx((i) => Math.min(slides.length - 1, i + 1)) }, "다음"))),
              React.createElement("div", { style: { borderRadius: "var(--r-md)", overflow: "hidden", boxShadow: "var(--sh-1)", border: "1px solid var(--border)" } },
                (typeof SlidePreview === "function")
                  ? React.createElement(SlidePreview, { slide })
                  : React.createElement("div", { style: { aspectRatio: "16/9", background: "var(--bg-normal)", display: "flex", alignItems: "center", justifyContent: "center", padding: 20 } },
                      React.createElement("div", { className: "t-headline-1", style: { color: "var(--label-normal)" } }, (slide && slide.title) || "슬라이드"))),
              /* 나레이션(있으면) — 읽기 보조 */
              slide && slide.narration
                ? React.createElement("div", { style: { marginTop: 14, background: "var(--bg-normal)", border: "1px solid var(--border)", borderRadius: "var(--r-md)", padding: "12px 14px" } },
                    React.createElement("div", { className: "t-caption-1", style: { color: "var(--label-alt)", fontWeight: 800, marginBottom: 5 } }, "나레이션"),
                    React.createElement("div", { className: "t-body-2", style: { color: "var(--label-neutral)", lineHeight: 1.65, whiteSpace: "pre-wrap" } }, slide.narration))
                : null,
              /* 썸네일 스트립 */
              React.createElement("div", { style: { display: "flex", gap: 7, overflowX: "auto", marginTop: 16, paddingBottom: 4 } },
                slides.map((s, i) => React.createElement("button", {
                  key: s.slideId || i, onClick: () => setIdx(i),
                  style: { flexShrink: 0, width: 96, cursor: "pointer", borderRadius: "var(--r-sm)", overflow: "hidden", border: "2px solid " + (i === idx ? "var(--primary)" : "var(--border)"), background: "var(--bg-normal)", padding: 0 },
                },
                  React.createElement("div", { style: { pointerEvents: "none" } },
                    (typeof SlidePreview === "function") ? React.createElement(SlidePreview, { slide: s }) : React.createElement("div", { style: { aspectRatio: "16/9" } }))))) ),

            /* 우: 코멘트(scope=comment 일 때만) */
            canComment
              ? React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 14 } },
                  React.createElement(GuestCommentComposer, { slideId: slide && slide.slideId, token, onPosted: () => loadComments() }),
                  React.createElement("div", null,
                    React.createElement("div", { className: "t-label-2", style: { color: "var(--label-neutral)", fontWeight: 800, marginBottom: 9 } }, "이 슬라이드 코멘트"),
                    React.createElement(GuestCommentList, { comments })))
              : null)),
    React.createElement("footer", { style: { borderTop: "1px solid var(--border)", padding: "14px 20px", textAlign: "center" } },
      React.createElement("span", { className: "t-caption-1", style: { color: "var(--label-assist)" } }, "Storyboard 로 공유된 스토리보드예요.")));
}

Object.assign(window, { ShareView, parseShareToken, GuestCommentComposer, GuestCommentList });
