/* global React, Footer, SiteHeader */
const { useState: useStateUp, useMemo: useMemoUp, useEffect: useEffectUp } = React;

const UP_KIND = {
  new:      { label: "New",      cls: "bg-orange-100 text-orange-800" },
  improved: { label: "Improved", cls: "bg-stone-200 text-stone-800" },
  fixed:    { label: "Fixed",    cls: "bg-emerald-100 text-emerald-800" },
};

const upDay = (s) => new Date(s + "T12:00:00");
const upFmt = (s) => upDay(s).toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" });
const upSlug = (e) => e.date + "-" + e.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
const upDaysAgo = (s) => Math.floor((Date.now() - upDay(s).getTime()) / 86400000);

// Every dated unit (entry or sub-item) counts toward activity.
function upUnits(list) {
  const out = [];
  list.forEach((e) => { out.push(e.date); (e.items || []).forEach((i) => out.push(i.date)); });
  return out;
}

function KindBadge({ kind }) {
  const k = UP_KIND[kind] || UP_KIND.improved;
  return <span className={"text-[11px] font-semibold px-2 py-0.5 rounded-full " + k.cls}>{k.label}</span>;
}

function PulseStrip({ list }) {
  const units = upUnits(list);
  const last30 = units.filter((d) => upDaysAgo(d) <= 30).length;
  const lastShip = Math.max(0, Math.min(...units.map(upDaysAgo)));
  // 12 weekly buckets, oldest first.
  const weeks = Array.from({ length: 12 }, () => 0);
  units.forEach((d) => {
    const w = Math.floor(upDaysAgo(d) / 7);
    if (w >= 0 && w < 12) weeks[11 - w] += 1;
  });
  const max = Math.max(1, ...weeks);
  return (
    <section className="pb-8">
      <div className="max-w-5xl mx-auto px-6">
        <div className="rounded-2xl border border-stone-200 bg-white p-6 grid sm:grid-cols-12 gap-6 items-end">
          <div className="sm:col-span-5 grid grid-cols-2 gap-4">
            <div>
              <div className="text-4xl font-bold text-stone-900 tracking-tight">{last30}</div>
              <div className="text-sm text-stone-600 mt-1">changes in the last 30 days</div>
            </div>
            <div>
              <div className="text-4xl font-bold text-stone-900 tracking-tight">{lastShip === 0 ? "Today" : lastShip + "d"}</div>
              <div className="text-sm text-stone-600 mt-1">{lastShip === 0 ? "last shipped" : "since the last change"}</div>
            </div>
          </div>
          <div className="sm:col-span-7">
            <div className="flex items-end gap-1.5 h-16" role="img" aria-label="Changes shipped per week over the last 12 weeks">
              {weeks.map((n, i) => (
                <div key={i} className="flex-1 flex flex-col justify-end h-full" title={n + " change" + (n === 1 ? "" : "s")}>
                  <div className={"rounded-sm " + (n ? "bg-orange-500" : "bg-stone-200")} style={{ height: n ? Math.max(8, (n / max) * 100) + "%" : "4px" }} />
                </div>
              ))}
            </div>
            <div className="flex justify-between text-[11px] text-stone-500 mt-2"><span>12 weeks ago</span><span>This week</span></div>
          </div>
        </div>
      </div>
    </section>
  );
}

function Chip({ active, onClick, children }) {
  return (
    <button type="button" onClick={onClick} aria-pressed={active}
      className={"text-sm font-medium px-3 py-1.5 rounded-full border transition-colors " + (active ? "bg-stone-900 text-white border-stone-900" : "bg-white text-stone-700 border-stone-200 hover:border-stone-400")}>
      {children}
    </button>
  );
}

function ItemList({ items }) {
  return (
    <ul className="space-y-2.5">
      {items.map((it, i) => (
        <li key={i} className="flex gap-3 text-[14px] text-stone-700 leading-snug">
          <span className="w-14 flex-none text-stone-500 text-xs pt-0.5">{upDay(it.date).toLocaleDateString("en-GB", { day: "numeric", month: "short" })}</span>
          <span className="flex-1">{it.text}</span>
          <span className="flex-none"><KindBadge kind={it.kind} /></span>
        </li>
      ))}
    </ul>
  );
}

// Headline feature: full write-up.
function MajorCard({ e }) {
  const id = upSlug(e);
  const [open, setOpen] = useStateUp(false);
  const n = (e.items || []).length;
  return (
    <article id={id} className="scroll-mt-24 rounded-3xl border border-stone-200 bg-white overflow-hidden">
      <div className="h-1.5 bg-gradient-to-r from-orange-500 to-orange-300" />
      <div className="p-6 sm:p-8">
        <div className="flex flex-wrap items-center gap-2 text-xs text-stone-600">
          <span className="text-[11px] uppercase tracking-[0.14em] font-bold text-orange-700">Major release</span>
          {e.badge && <span className="text-[11px] font-bold px-2 py-0.5 rounded-full bg-stone-900 text-white">{e.badge}</span>}
          <span className="text-stone-300">·</span>
          <a href={"#" + id} className="font-medium hover:text-stone-900">{upFmt(e.date)}</a>
          <span className="text-stone-300">·</span>
          <span className="font-medium">{e.area}</span>
        </div>
        <h3 className="font-bold text-stone-900 tracking-tight mt-3" style={{ fontSize: "clamp(24px, 3vw, 34px)", lineHeight: 1.1, letterSpacing: "-0.02em" }}>{e.title}</h3>
        <p className="text-lg text-stone-800 leading-snug mt-2 font-medium">{e.tagline}</p>
        <div className="grid md:grid-cols-2 gap-6 mt-6">
          <div>
            <div className="text-xs uppercase tracking-wider font-semibold text-stone-500 mb-1.5">What it is</div>
            <p className="text-[15px] text-stone-700 leading-relaxed">{e.what}</p>
          </div>
          <div>
            <div className="text-xs uppercase tracking-wider font-semibold text-stone-500 mb-1.5">What it's for</div>
            <p className="text-[15px] text-stone-700 leading-relaxed">{e.usedFor}</p>
          </div>
        </div>
        {(e.highlights || []).length > 0 && (
          <ul className="grid sm:grid-cols-2 gap-x-6 gap-y-2 mt-6 pt-6 border-t border-stone-100">
            {e.highlights.map((h, i) => (
              <li key={i} className="flex gap-2.5 text-[14px] text-stone-800 leading-snug">
                <span className="mt-1.5 w-1.5 h-1.5 rounded-full bg-orange-500 flex-none" />
                <span>{h}</span>
              </li>
            ))}
          </ul>
        )}
        {n > 0 && (
          <div className="mt-5">
            <button type="button" onClick={() => setOpen(!open)} aria-expanded={open}
              className="text-sm font-medium text-orange-700 hover:text-orange-800">
              {open ? "Hide follow-up changes" : "Show " + n + " follow-up change" + (n === 1 ? "" : "s")}
            </button>
            {open && <div className="mt-3 border-t border-stone-100 pt-3"><ItemList items={e.items} /></div>}
          </div>
        )}
      </div>
    </article>
  );
}

// Tweak or improvement: compact row.
function MinorRow({ e }) {
  const id = upSlug(e);
  const [open, setOpen] = useStateUp(false);
  const n = (e.items || []).length;
  return (
    <article id={id} className="scroll-mt-24 py-4">
      <div className="flex flex-wrap items-center gap-2 text-xs text-stone-600">
        <a href={"#" + id} className="font-medium hover:text-stone-900">{upFmt(e.date)}</a>
        <span className="text-stone-300">·</span>
        <span className="font-medium">{e.area}</span>
        <KindBadge kind={e.kind} />
      </div>
      <h4 className="text-[15px] font-semibold text-stone-900 mt-1.5">{e.title}</h4>
      <p className="text-[14px] text-stone-700 leading-relaxed mt-0.5">{e.summary}</p>
      {n > 0 && (
        <>
          <button type="button" onClick={() => setOpen(!open)} aria-expanded={open}
            className="mt-2 text-[13px] font-medium text-orange-700 hover:text-orange-800">
            {open ? "Hide details" : "Show " + n + " detail" + (n === 1 ? "" : "s")}
          </button>
          {open && <div className="mt-2.5"><ItemList items={e.items} /></div>}
        </>
      )}
    </article>
  );
}

function UpdatesPage() {
  const all = window.UPDATES || [];
  const [area, setArea] = useStateUp("All");
  const [kind, setKind] = useStateUp("all");
  const [showAllMajor, setShowAllMajor] = useStateUp(false);
  const [showOlder, setShowOlder] = useStateUp(false);
  const areas = useMemoUp(() => ["All", ...Array.from(new Set(all.map((e) => e.area))).sort()], [all]);

  const filtered = all.filter((e) => (area === "All" || e.area === area) && (kind === "all" || e.kind === kind || (e.items || []).some((i) => i.kind === kind)));
  const majors = filtered.filter((e) => e.tier === "major");
  const minors = filtered.filter((e) => e.tier !== "major");
  const MAJOR_SHOWN = 5;
  const majorsShown = showAllMajor ? majors : majors.slice(0, MAJOR_SHOWN);

  const cutoff = 120; // days of tweaks shown by default
  const recentMin = minors.filter((e) => upDaysAgo(e.date) <= cutoff);
  const olderMin = minors.filter((e) => upDaysAgo(e.date) > cutoff);
  const shownMin = showOlder || recentMin.length === 0 ? minors : recentMin;

  const groups = [];
  shownMin.forEach((e) => {
    const m = upDay(e.date).toLocaleDateString("en-GB", { month: "long", year: "numeric" });
    const g = groups[groups.length - 1];
    if (g && g.m === m) g.items.push(e); else groups.push({ m, items: [e] });
  });

  useEffectUp(() => {
    if (location.hash) {
      setShowAllMajor(true); setShowOlder(true);
      setTimeout(() => { const el = document.getElementById(location.hash.slice(1)); if (el) el.scrollIntoView(); }, 50);
    }
  }, []);

  return (
    <>
      <SiteHeader active="updates" cta={{ label: "Start free trial", href: "contact.html" }}
        breadcrumb={[{ label: "Updates", href: "updates.html" }, { label: "What's new" }]} />
      <main>
        <section className="pt-16 lg:pt-20 pb-10">
          <div className="max-w-5xl mx-auto px-6">
            <span className="text-[11px] uppercase tracking-[0.18em] font-semibold text-orange-700">Updates</span>
            <h1 className="font-bold tracking-tight text-stone-900 mt-3" style={{ fontSize: "clamp(36px, 5vw, 60px)", lineHeight: 1.04, letterSpacing: "-0.025em" }}>
              We ship every week.
            </h1>
            <p className="text-[17px] text-stone-700 leading-relaxed mt-5 max-w-2xl">
              Big new features first, then the steady stream of improvements and fixes, each with the date it landed. Nothing here is a roadmap promise; it's all live.
            </p>
          </div>
        </section>
        <PulseStrip list={all} />
        <section className="pb-16">
          <div className="max-w-5xl mx-auto px-6">
            <div className="flex flex-wrap gap-2 mb-3" role="group" aria-label="Filter by area">
              {areas.map((a) => <Chip key={a} active={area === a} onClick={() => setArea(a)}>{a}</Chip>)}
            </div>
            <div className="flex flex-wrap gap-2 mb-12" role="group" aria-label="Filter by type">
              <Chip active={kind === "all"} onClick={() => setKind("all")}>All types</Chip>
              {Object.entries(UP_KIND).map(([k, v]) => <Chip key={k} active={kind === k} onClick={() => setKind(k)}>{v.label}</Chip>)}
            </div>

            {majors.length > 0 && (
              <div className="mb-16">
                <h2 className="font-bold text-stone-900 tracking-tight mb-1" style={{ fontSize: "clamp(24px, 3vw, 32px)" }}>Major releases</h2>
                <p className="text-stone-600 text-[15px] mb-6">New capabilities, what they do and what they're for.</p>
                <div className="space-y-6">
                  {majorsShown.map((e) => <MajorCard key={upSlug(e)} e={e} />)}
                </div>
                {!showAllMajor && majors.length > MAJOR_SHOWN && (
                  <button type="button" onClick={() => setShowAllMajor(true)}
                    className="mt-6 text-sm font-medium px-4 py-2 rounded-lg border border-stone-300 text-stone-800 hover:bg-stone-100">
                    Show {majors.length - MAJOR_SHOWN} earlier major release{majors.length - MAJOR_SHOWN === 1 ? "" : "s"}
                  </button>
                )}
              </div>
            )}

            {minors.length > 0 && (
              <div>
                <h2 className="font-bold text-stone-900 tracking-tight mb-1" style={{ fontSize: "clamp(24px, 3vw, 32px)" }}>Tweaks and improvements</h2>
                <p className="text-stone-600 text-[15px] mb-8">Smaller changes, polish and fixes.</p>
                {groups.map((g) => (
                  <div key={g.m} className="mb-8">
                    <h3 className="text-sm uppercase tracking-wider font-semibold text-stone-500 mb-1">{g.m}</h3>
                    <div className="divide-y divide-stone-200 border-t border-b border-stone-200">
                      {g.items.map((e) => <MinorRow key={upSlug(e)} e={e} />)}
                    </div>
                  </div>
                ))}
                {!showOlder && olderMin.length > 0 && recentMin.length > 0 && (
                  <button type="button" onClick={() => setShowOlder(true)}
                    className="text-sm font-medium px-4 py-2 rounded-lg border border-stone-300 text-stone-800 hover:bg-stone-100">
                    Show {olderMin.length} older tweak{olderMin.length === 1 ? "" : "s"}
                  </button>
                )}
              </div>
            )}
            {majors.length === 0 && minors.length === 0 && <p className="text-stone-600">Nothing matches those filters.</p>}
          </div>
        </section>
      </main>
      <Footer />
    </>
  );
}

window.UpdatesPage = UpdatesPage;
