/* comments.jsx — per-article comment widget, backed by the Cloudflare Worker.
   Renders comment text as React children (auto-escaped) — defence in depth on
   top of the Worker's server-side HTML escaping. Config from window.COMMENTS_CONFIG. */

const { useState: useCS, useEffect: useCE } = React;

const NAME_MAX = 80;
const BODY_MAX = 4000;

function commentDate(ms) {
  try {
    return new Date(ms).toLocaleDateString(undefined, {
      year: "numeric", month: "short", day: "numeric",
    });
  } catch (e) { return ""; }
}

function Comments({ slug }) {
  const cfg = (window.COMMENTS_CONFIG || {});
  const apiBase = (cfg.apiBase || "").replace(/\/$/, "");
  const endpoint = apiBase + "/api/comments";

  const [comments, setComments] = useCS([]);
  const [loading, setLoading] = useCS(true);
  const [loadError, setLoadError] = useCS("");
  const [name, setName] = useCS("");
  const [body, setBody] = useCS("");
  const [website, setWebsite] = useCS(""); // honeypot — stays empty for humans
  const [submitting, setSubmitting] = useCS(false);
  const [formError, setFormError] = useCS("");
  const [done, setDone] = useCS(false);

  useCE(() => {
    if (!slug) return;
    let cancelled = false;
    setLoading(true); setLoadError("");
    fetch(`${endpoint}?slug=${encodeURIComponent(slug)}&_=${Date.now()}`,
      { headers: { Accept: "application/json" }, cache: "no-store" })
      .then((res) => { if (!res.ok) throw new Error("load"); return res.json(); })
      .then((data) => { if (cancelled) return; setComments((data && data.comments) || []); setLoading(false); })
      .catch(() => { if (cancelled) return; setLoadError("Could not load comments."); setLoading(false); });
    return () => { cancelled = true; };
  }, [slug, endpoint]);

  function submit(ev) {
    ev.preventDefault();
    setFormError("");
    const n = name.trim(), b = body.trim();
    if (n.length < 1) return setFormError("Please enter your name.");
    if (n.length > NAME_MAX) return setFormError("Name is too long.");
    if (b.length < 1) return setFormError("Please write a comment.");
    if (b.length > BODY_MAX) return setFormError("Comment is too long.");

    setSubmitting(true);
    fetch(endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ slug, name: n, body: b, website }),
    })
      .then((res) => res.json().then((data) => ({ ok: res.ok, data })))
      .then(({ ok, data }) => {
        setSubmitting(false);
        if (!ok) { setFormError((data && data.error) || "Could not post your comment."); return; }
        if (data && data.comment) setComments((prev) => prev.concat([data.comment]));
        setName(""); setBody(""); setDone(true);
        window.track && window.track("comment_submitted", { slug: slug, language: window.SITE_LANG });
      })
      .catch(() => { setSubmitting(false); setFormError("Network error. Please try again."); });
  }

  const count = comments.length;

  return (
    <React.Fragment>
      <h2 className="comments-title">Comments</h2>
      <p className="comments-count">
        {loading ? "Loading…" : count === 0 ? "No comments yet." : `${count} ${count === 1 ? "comment" : "comments"}`}
      </p>

      {done ? (
        <p className="comment-note">Thank you — your comment has been posted.</p>
      ) : (
        <form className="comment-form" onSubmit={submit}>
          <input type="text" placeholder="Your name" value={name} maxLength={NAME_MAX}
            disabled={submitting} onChange={(e) => setName(e.target.value)} aria-label="Your name" />
          <textarea placeholder="Write a comment…" value={body} maxLength={BODY_MAX}
            disabled={submitting} onChange={(e) => setBody(e.target.value)} aria-label="Your comment" />
          {/* honeypot: hidden from humans; bots that fill it are silently dropped */}
          <div className="comment-hp" aria-hidden="true">
            <label>Website<input type="text" tabIndex={-1} autoComplete="off"
              value={website} onChange={(e) => setWebsite(e.target.value)} /></label>
          </div>
          <div className="comment-form-row">
            <span className={`comment-note ${formError ? "is-error" : ""}`}>
              {formError || "Be kind. Comments are public."}
            </span>
            <button type="submit" className="comment-submit" disabled={submitting}>
              {submitting ? "Posting…" : "Post comment"}
            </button>
          </div>
        </form>
      )}

      {loadError ? (
        <p className="comment-note is-error">{loadError}</p>
      ) : count > 0 ? (
        <ol className="comment-list">
          {comments.map((c) => (
            <li key={c.id} className="comment">
              <div className="comment-head">
                <span className="comment-name">{c.name}</span>
                <span className="comment-date">{commentDate(c.created_at)}</span>
              </div>
              <p className="comment-body">{c.body}</p>
            </li>
          ))}
        </ol>
      ) : null}
    </React.Fragment>
  );
}

window.Comments = Comments;
