// changelog.jsx — Version + "What's new" surface.
//
// Single source of truth: /public/changelog.json. The shell shows a
// version chip (e.g. "v1.0.0") at the bottom of the sidebar; clicking it
// opens this modal which renders every release with its Added / Changed
// / Fixed sections. A pink dot pulses on the chip when the latest
// version differs from what the user last acknowledged (stored in
// localStorage), so people know there's something new to look at.
//
// Public surface:
//   window.WhatsNewModal          — the modal component
//   window.VersionChip            — sidebar footer chip (with new-dot)
//   window.flowboardVersion       — shorthand for the current version string
//   window.flowboardChangelog     — promise that resolves to the full data
//   window.markVersionSeen()      — clears the new-dot for the current version

const CHANGELOG_URL = "/changelog.json";
const LS_LAST_SEEN  = "flowboard.version.lastSeen";

let _cached = null;
async function loadChangelog() {
  if (_cached) return _cached;
  try {
    const r = await fetch(CHANGELOG_URL, { cache: "no-cache" });
    if (!r.ok) throw new Error("changelog fetch " + r.status);
    _cached = await r.json();
  } catch (e) {
    console.warn("[changelog] load failed:", e && e.message);
    _cached = { version: "?", releases: [] };
  }
  return _cached;
}

function lastSeenVersion() {
  try { return localStorage.getItem(LS_LAST_SEEN) || ""; } catch { return ""; }
}
function markVersionSeen(v) {
  try { localStorage.setItem(LS_LAST_SEEN, v || ""); } catch {}
}

function VersionChip({ onClick }) {
  const [version, setVersion] = React.useState(window.flowboardVersion || "");
  const [unseen, setUnseen]   = React.useState(false);

  React.useEffect(() => {
    let cancelled = false;
    loadChangelog().then(c => {
      if (cancelled) return;
      const v = (c && c.version) || "";
      setVersion(v);
      setUnseen(!!v && lastSeenVersion() !== v);
      window.flowboardVersion = v;
    });
    return () => { cancelled = true; };
  }, []);

  if (!version) return null;
  return (
    <button type="button"
            className={`sb-version ${unseen ? "is-unseen" : ""}`}
            title={unseen ? "Updated — click to see what's new" : "What's new"}
            onClick={() => {
              setUnseen(false);
              markVersionSeen(version);
              onClick && onClick();
            }}>
      <span className="sb-version-tag">v{version}</span>
      <span className="sb-version-label">What's new</span>
      {unseen && <span className="sb-version-dot" aria-hidden="true"/>}
    </button>
  );
}

function WhatsNewModal({ onClose }) {
  const [data, setData] = React.useState(null);
  const [error, setError] = React.useState("");

  React.useEffect(() => {
    let cancelled = false;
    loadChangelog().then(c => {
      if (cancelled) return;
      setData(c);
      // Mark the current version as seen the moment the modal opens.
      if (c && c.version) markVersionSeen(c.version);
    }).catch(e => { if (!cancelled) setError(e.message || "Failed to load."); });
    return () => { cancelled = true; };
  }, []);

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal whatsnew-modal" onClick={e => e.stopPropagation()}>
        <div className="modal-header">
          <div>
            <div className="modal-title">What's new</div>
            <div className="modal-subtitle">
              {data && data.version
                ? <>Latest version <code className="whatsnew-tag">v{data.version}</code></>
                : "Loading…"}
            </div>
          </div>
          <button className="modal-close" onClick={onClose}>✕</button>
        </div>
        <div className="modal-body whatsnew-body">
          {error && <div className="whatsnew-error">{error}</div>}
          {!data ? (
            <div className="whatsnew-loading">Loading changelog…</div>
          ) : !data.releases || data.releases.length === 0 ? (
            <div className="whatsnew-loading">No releases yet.</div>
          ) : (
            data.releases.map(r => <ReleaseCard key={r.version} release={r}/>)
          )}
        </div>
        <div className="modal-footer">
          <button className="btn btn-primary" onClick={onClose}>Got it</button>
        </div>
      </div>
    </div>
  );
}

function ReleaseCard({ release }) {
  const sections = [
    { key: "added",   label: "Added",   tone: "added",   items: release.added   || [] },
    { key: "changed", label: "Changed", tone: "changed", items: release.changed || [] },
    { key: "fixed",   label: "Fixed",   tone: "fixed",   items: release.fixed   || [] },
  ].filter(s => s.items.length > 0);

  const dateLabel = release.date
    ? new Date(release.date).toLocaleDateString(undefined, {
        year: "numeric", month: "long", day: "numeric",
      })
    : "";

  return (
    <section className="whatsnew-release">
      <header className="whatsnew-release-head">
        <h3 className="whatsnew-release-title">
          <span className="whatsnew-tag">v{release.version}</span>
          {release.title && <span>{release.title}</span>}
        </h3>
        {dateLabel && <span className="whatsnew-release-date">{dateLabel}</span>}
      </header>
      {sections.length === 0 && (
        <div className="whatsnew-empty">No notes for this release.</div>
      )}
      {sections.map(s => (
        <div key={s.key} className={`whatsnew-section is-${s.tone}`}>
          <div className="whatsnew-section-label">{s.label}</div>
          <ul className="whatsnew-list">
            {s.items.map((it, i) => <li key={i}>{it}</li>)}
          </ul>
        </div>
      ))}
    </section>
  );
}

window.flowboardChangelog = loadChangelog;
window.markVersionSeen    = markVersionSeen;
Object.assign(window, { WhatsNewModal, VersionChip });
