const { useEffect: useEffectHSW, useState: useStateHSW } = React;

function HowStatusWorks() {
  const [now, setNow] = useStateHSW(new Date());
  useEffectHSW(() => {
    const i = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(i);
  }, []);

  return (
    <React.Fragment>
      <Header now={now} />
      <main className="shell">
        <div className="incident-page-nav">
          <a href="/">← Back to status</a>
        </div>
        <article className="doc">
          <header className="doc-head">
            <p className="doc-eyebrow">Behind the scenes</p>
            <h1 className="doc-title">How this status page works</h1>
            <p className="doc-lede">
              Every dot, bar, and percentage on the front page comes from real probes hitting real
              endpoints — no manual switches, no curated views. This page documents exactly how those
              measurements are taken, smoothed, and surfaced.
            </p>
          </header>

          <nav className="doc-toc">
            <a href="#monitoring">1. What we monitor</a>
            <a href="#prober">2. The prober loop</a>
            <a href="#flap">3. Flap protection</a>
            <a href="#bars">4. History bars &amp; smoothing</a>
            <a href="#uptime">5. Uptime % calculation</a>
            <a href="#incidents">6. Incidents &amp; the operator overlay</a>
            <a href="#maintenance">7. Maintenance windows</a>
            <a href="#refresh">8. Refresh cadence</a>
          </nav>

          <section id="monitoring" className="doc-section">
            <h2>1. What we monitor</h2>
            <p>
              Every service shown on the front page corresponds to a <em>monitor</em> — a single,
              configurable probe targeted at one specific endpoint. Three probe types are supported,
              each chosen to match what the underlying service actually exposes:
            </p>
            <ul className="doc-list">
              <li>
                <strong>HTTPS</strong> — issued via cURL with follow-redirects (up to 10 hops) and a
                hard request timeout. A response is considered <em>up</em> when the final HTTP status
                is below 500 and the round-trip time is below the monitor&apos;s configured
                <em> response threshold</em>. Note that 4xx counts as up — a 401 or 404 means the
                server is alive and answering requests, it&apos;s just refusing this particular one
                (no auth, rate-limit, missing path). Above the threshold the response is
                <em> degraded</em>; on connection failure, TLS error, timeout, or 5xx terminal
                status it is <em>down</em>.
              </li>
              <li>
                <strong>TCP</strong> — opens a raw socket to <code>host:port</code> and closes it
                immediately on success. Same threshold semantics for degraded/down apply, using the
                socket-open latency as the measurement.
              </li>
              <li>
                <strong>Ping</strong> — sends a single ICMP echo request with a 3-second timeout via
                the system <code>ping</code> utility. Used for hosts that don&apos;t expose an
                application-layer endpoint we&apos;d want to probe directly.
              </li>
            </ul>
            <p>
              Each monitor carries its own <strong>interval</strong> (how often it&apos;s probed, default
              60 s), <strong>response threshold</strong> (the latency line between <em>up</em> and
              <em> degraded</em>), and two visibility flags: whether the monitor appears publicly at
              all, and whether it counts toward the aggregate 30-day uptime headline.
            </p>
            <p className="doc-callout">
              <strong>Single vantage point.</strong> All checks are run from one place: our VPS in
              Hetzner&apos;s {/* TODO: fill in actual region on first deploy */} datacenter. A regional
              connectivity issue between that VPS and a target service looks identical to that
              service being down. For services with broad geographic audiences, treat the numbers
              on this page as &ldquo;up from where we&apos;re looking,&rdquo; not &ldquo;up everywhere.&rdquo;
            </p>
          </section>

          <section id="prober" className="doc-section">
            <h2>2. The prober loop</h2>
            <p>
              A dedicated sidecar process — completely separate from the web server — wakes up every
              10 seconds and asks the database which monitors are due. A monitor becomes due when the
              time since its last successful probe exceeds its configured interval, or when it&apos;s
              been touched by an operator (e.g., a manual &ldquo;run check now&rdquo;).
            </p>
            <p>
              Probes run in sequence within a tick; each result is written atomically with a precise
              timestamp. The prober is the <em>only</em> writer to the per-check history — the web
              UI and admin panel never invent probe data.
            </p>
            <p className="doc-callout">
              <strong>Why a sidecar?</strong> Decoupling the probe loop from the request-serving
              process means probes keep running at a steady cadence regardless of frontend traffic,
              and a slow probe (e.g., a 30-second HTTPS timeout) never blocks a status page load.
            </p>
          </section>

          <section id="flap" className="doc-section">
            <h2>3. Flap protection</h2>
            <p>
              Networks are noisy. A single slow response or a one-off TCP reset is almost never a
              real incident — it&apos;s a transient blip that resolves on the next tick. If the page
              flipped to <em>degraded</em> the moment one bad probe landed, the status would jitter
              between green and orange constantly, and the signal-to-noise ratio of every dashboard
              would collapse.
            </p>
            <p>
              To prevent that, the displayed status of a monitor is derived from a small window of
              the most recent probes, not from any single one. The rule tolerates a single transient
              failure inside the window — one bad probe out of five doesn&apos;t move the dot. A
              service has to be consistently bad to be reported as bad.
            </p>
            <p>
              Crucially, a service that&apos;s genuinely <em>intermittent</em> — flapping between
              healthy and unhealthy probes — shows as <strong>degraded</strong>, not green. This is
              the change a status page is most often quietly wrong about: an alternating
              up/down/up/down service responding correctly half the time is by definition not fully
              operational, and the page says so. A monitor only resolves to <em>down</em> when the
              recent window contains no successful probes at all.
            </p>
            <p>
              The exact thresholds (window size, blip-tolerance count) live in the
              <code> decide_displayed_status()</code> function on the server — the truth table is
              right there in its docblock if you want the precise rule. The same logic runs on both
              the probe-write path and any operator-driven edits to probe history, so the dot can
              never end up disagreeing with the probes that produced it.
            </p>
          </section>

          <section id="bars" className="doc-section">
            <h2>4. History bars &amp; smoothing</h2>
            <p>
              Each service row shows a strip of coloured bars summarising the recent past. We render
              three resolutions on request:
            </p>
            <ul className="doc-list">
              <li><strong>1 hour</strong> — 60 one-minute buckets</li>
              <li><strong>1 day</strong> — 24 one-hour buckets</li>
              <li><strong>7 / 30 / 90 days</strong> — daily buckets, the last N of the rolling 90-day window</li>
            </ul>
            <p>
              A bucket&apos;s colour is the <em>worst</em> probe outcome that landed inside it: green
              if every probe in that window was up, orange if any was degraded, red if any was down.
              Buckets with no probes at all show as &ldquo;no data&rdquo; (a muted grey).
            </p>
            <p>
              Two pieces of post-processing run on top of the raw bucket grid before display:
            </p>
            <ul className="doc-list">
              <li>
                <strong>Run smoothing.</strong> A run of bad buckets shorter than three consecutive
                slots is rewritten to operational, on the assumption that a single isolated bad
                bucket between long stretches of green is more likely a transient than a real
                degradation worth alarming on.
              </li>
              <li>
                <strong>Short-gap filling.</strong> Isolated &ldquo;no data&rdquo; buckets sandwiched
                between operational neighbours — usually caused by a slow probe pushing the next one
                across a bucket boundary — are filled in as operational. Genuinely empty stretches
                (longer gaps, or gaps next to bad data) stay as no-data.
              </li>
            </ul>
            <p>
              Bucket boundaries are anchored to the wall clock, not to &ldquo;seconds ago&rdquo; from
              the moment of the page load. That means refreshing mid-minute doesn&apos;t shift
              probes between buckets; everyone looking at the page at the same instant sees the same
              bar grid.
            </p>
            <p className="doc-callout">
              <strong>The bars and the uptime percentage are two different views of the same data
              — and they intentionally disagree on short outages.</strong> The bars apply the
              run-smoothing described above so the recent-history strip is denoised and skimmable;
              the uptime percentage (next section) is computed from raw probe rows with no smoothing
              at all. Practical consequence: a real 1–2 minute outage can be visible in the
              percentage and invisible in the 1-hour bar grid, because the bad minute-bucket gets
              smoothed back to green. This is a deliberate design choice — bars are for visual
              pattern recognition over time, the percentage is the authoritative number. If you
              need to chase down a brief failure, trust the percentage and the per-check log, not
              the bars.
            </p>
          </section>

          <section id="uptime" className="doc-section">
            <h2>5. Uptime % calculation</h2>
            <p>
              The percentage shown next to each service and the aggregate 30-day headline at the top
              of the page are <strong>the same calculation, run server-side, over the same probe
              rows</strong>. Both numbers come straight from <code>monitor_checks</code> — no
              smoothing, no operator override, no client-side recompute. The math is intentionally
              simple:
            </p>
            <p className="doc-code">
              uptime % = (count of probes with status = up) ÷ (count of probes in the last 30 days) × 100
            </p>
            <p>
              The per-row number reflects whichever range tab is currently selected at the top of
              the page — switching between 1h, 1d, 7d, 30d, 90d moves both the bars <em>and</em>
              the number together, so the two views always tell the same story over the same
              window. The label next to the percentage changes too (&ldquo;1-hour uptime&rdquo;,
              &ldquo;24-hour uptime&rdquo;, etc.) so it&apos;s always obvious which window
              you&apos;re looking at.
            </p>
            <p>
              The 30-day uptime at the very top of the page is anchored at 30 days regardless of
              the per-row range selection. That number is the at-a-glance summary; the per-row
              numbers are scoped to whatever you&apos;re currently inspecting. The headline also
              counts only monitors flagged as contributing to uptime, so high-frequency canaries
              and external dependencies can be monitored without dragging it up or down.
            </p>
            <p>
              All numbers — per-row and headline — are computed server-side from raw
              <code> monitor_checks</code> rows. No smoothing, no client-side recompute. A
              two-minute outage shows up in the percentage at any range that includes it, whether
              or not it&apos;s visible in the bars (the bars apply the run-length smoothing
              described in §4; the percentage doesn&apos;t).
            </p>
            <p>
              A monitor that has never produced a probe row shows the uptime number as an em-dash
              rather than 100%. The page would rather say &ldquo;we don&apos;t know yet&rdquo; than
              fabricate a perfect score on no evidence.
            </p>
          </section>

          <section id="incidents" className="doc-section">
            <h2>6. Incidents &amp; the operator overlay</h2>
            <p>
              When something visible is happening — a partial outage, a third-party dependency
              degradation, a deploy gone sideways — the on-call operator opens an <em>incident</em>
              and tags the affected services. The incident has a severity (minor or major) and a
              running set of timestamped updates from the response team.
            </p>
            <p>
              Incidents change the page in two visible ways, both subject to the same rule:
              <strong> the incident colour only wins when it&apos;s strictly worse than what the
              probes are actually seeing.</strong>
            </p>
            <ul className="doc-list">
              <li>
                Affected service dots and the history bars covering the incident window pick up the
                incident colour — but only where the probe-derived colour for that bucket or dot is
                <em> less</em> severe. If the probes are already reporting a service as down (red),
                a freshly declared minor incident (orange) does not visually downgrade the bars or
                the dot to orange. The probes win on ties.
              </li>
              <li>
                The headline banner at the top reflects the worst of <em>(probe-derived state,
                operator-declared severity)</em>, so an operator-only incident still shows up there
                even when every probe is green. The headline can be pushed up by either signal but
                not pulled down by either.
              </li>
            </ul>
            <p>
              The reasoning: probes are observed data; incident severity is operator opinion. When
              they agree on the rank, the observation is what gets shown. When the operator&apos;s
              read of the situation is worse than what the probes have caught (because they have
              human context the probes lack), the operator&apos;s read wins. The reverse — operator
              opinion masking a real outage — is the failure mode this rule exists to prevent.
            </p>
            <p>
              Crucially, <strong>incidents do not change the uptime numbers or the operational
              counter</strong>. Those remain probe-driven. An operator declaring a minor incident
              with no probe failures is a transparency choice (&ldquo;we know about this, we&apos;re
              working on it&rdquo;), not a falsification of the numeric record. If a real failure is
              happening alongside the incident, the probes will see it and the uptime % will move on
              its own.
            </p>
          </section>

          <section id="maintenance" className="doc-section">
            <h2>7. Maintenance windows</h2>
            <p>
              Planned work is announced ahead of time as a <em>maintenance window</em>: a title, a
              start/end timestamp, a list of affected services, and an expected impact level.
              Upcoming windows appear in their own section on the front page so customers can plan
              around them.
            </p>
            <p>
              Maintenance windows are an announcement layer only — they don&apos;t alter probe
              behaviour, suppress incidents, or change uptime calculation. If we take a service down
              for maintenance and that produces real probe failures, those failures count in the
              same way an unplanned outage would. Honest numbers over flattering numbers, every
              time.
            </p>
          </section>

          <section id="refresh" className="doc-section">
            <h2>8. Refresh cadence &amp; the prober heartbeat</h2>
            <p>
              The front page polls a single rollup endpoint every <strong>30 seconds</strong> in the
              background. The clock in the header ticks every second to make it obvious the page is
              live. The prober writes new probe results into the database at its own pace, so within
              a minute or so of any change, the page reflects it.
            </p>
            <p>
              The prober also writes a <strong>heartbeat</strong> to the database at the end of
              every successful tick — separate from any individual probe result. If a probe fails,
              that failure gets recorded normally and the heartbeat still advances; the heartbeat is
              tracking the liveness of the prober itself, not the health of the services it
              measures.
            </p>
            <p>
              If the heartbeat goes silent for several minutes, the page assumes the prober is dead
              and switches to a loss-of-signal mode: a clearly distinct gray dot on every service,
              an em-dash in place of every uptime number, and a yellow warning banner at the top of
              the page explaining how long it&apos;s been since the last successful probe. This is
              the one case where probe-derived colours and incident overlays are both ignored —
              once we&apos;ve lost contact with the data source, no green / orange / red colour
              would mean anything honest. &ldquo;Status unknown&rdquo; is the only correct answer,
              and that&apos;s what the page says.
            </p>
          </section>

          <footer className="doc-foot">
            <p className="muted">
              Questions about a specific number, an incident, or how a service is configured?
              Email <a href="mailto:customers@dmu.gr">customers@dmu.gr</a> — we&apos;ll happily
              walk through it.
            </p>
            <a className="doc-back" href="/">← Back to status</a>
          </footer>
        </article>
        <Footer />
      </main>
    </React.Fragment>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<HowStatusWorks />);
