<?php
// atzenix status page, renders ONLY from cache.json written by the monitor
// agent (cron, 5 min). No database, no sessions: the page stays servable when
// the panel backend itself is having a bad day.
$cache = @json_decode((string)@file_get_contents(__DIR__ . '/cache.json'), true) ?: null;
$stale = $cache === null || (time() - strtotime($cache['generated_at'] ?? '2000-01-01')) > 900;
$overall = $stale ? 'unknown' : ($cache['overall'] ?? 'unknown');
$comps = $cache['components'] ?? [];
$incidents = $cache['incidents'] ?? [];
$announcements = $cache['announcements'] ?? [];
$ago = fn(string $iso) => max(0, time() - strtotime($iso));
$fmtAgo = function (int $s): string {
    if ($s < 60) return "$s seconds ago";
    if ($s < 3600) return floor($s / 60) . ' minutes ago';
    if ($s < 86400) return floor($s / 3600) . ' hours ago';
    return floor($s / 86400) . ' days ago';
};
$STATE = ['operational' => ['All systems operational', 'ok'],
          'outage' => ['Service disruption in progress', 'bad'],
          'unknown' => ['Monitor status unknown', 'unknown']];
[$overallText, $overallCls] = $STATE[$overall] ?? $STATE['unknown'];
$sev = ['emergency' => ['Emergency', 'bad'], 'maintenance' => ['Maintenance', 'warn'], 'info' => ['Notice', 'info']];
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-store');
?><!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>atzenix status</title>
<meta http-equiv="refresh" content="60">
<style>
  :root {
    --bg: #0a0d14; --bg-card: #0f131c; --bg-raise: #141926;
    --line-strong: #2c3850;
    --text: #e8e6e1; --text-soft: #9aa3b2; --text-dim: #667080;
    --accent: #c8aa82; --accent-dim: #8a7557;
    --ok: #52c98a; --bad: #e06c6c; --warn: #d9a662; --info: #7ba7d9;
  }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    background: var(--bg); color: var(--text);
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    font-size: 15px; line-height: 1.55;
    -webkit-font-smoothing: antialiased;
  }
  .mono { font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', monospace; }
  .wrap { max-width: 780px; margin: 0 auto; padding: 0 1.25rem 4rem; }

  header { padding: 2.75rem 0 1.75rem; display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
  .brand { font-family: 'JetBrains Mono', ui-monospace, monospace; font-weight: 700; font-size: 1rem; letter-spacing: 0.04em; color: var(--text); text-decoration: none; }
  .brand span { color: var(--accent); }
  .brand-sub { color: var(--text-dim); font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; }

  .hero {
    border: 1px solid var(--line); border-top: 3px solid var(--accent);
    background: var(--bg-card); padding: 1.9rem 2rem; margin-bottom: 2rem;
    display: flex; align-items: center; gap: 1.1rem;
  }
  .hero.ok { border-top-color: var(--ok); }
  .hero.bad { border-top-color: var(--bad); }
  .hero.unknown { border-top-color: var(--warn); }
  .pulse { width: 13px; height: 13px; border-radius: 50%; flex-shrink: 0; animation: pulse 2.4s infinite; }
  .hero.ok .pulse { background: var(--ok); box-shadow: 0 0 0 0 rgba(82, 201, 138, 0.5); }
  .hero.bad .pulse { background: var(--bad); box-shadow: 0 0 0 0 rgba(224, 108, 108, 0.5); }
  .hero.unknown .pulse { background: var(--warn); box-shadow: 0 0 0 0 rgba(217, 166, 98, 0.5); }
  @keyframes pulse { 0% { box-shadow: 0 0 0 0 currentColor; opacity: 1; } 70% { box-shadow: 0 0 0 12px transparent; opacity: 0.85; } 100% { box-shadow: 0 0 0 0 transparent; opacity: 1; } }
  .hero h1 { font-size: 1.3rem; font-weight: 700; letter-spacing: -0.01em; }
  .hero.ok h1 { color: var(--ok); } .hero.bad h1 { color: var(--bad); } .hero.unknown h1 { color: var(--warn); }
  .hero .meta { margin-left: auto; text-align: right; color: var(--text-dim); font-size: 0.74rem; white-space: nowrap; }

  h2.section { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent-dim); margin: 2.25rem 0 0.9rem; }

  .comp { border: 1px solid var(--line); background: var(--bg-card); padding: 1rem 1.25rem; margin-bottom: 0.5rem; }
  .comp-top { display: flex; align-items: center; gap: 0.75rem; }
  .comp-name { font-weight: 600; font-size: 0.92rem; }
  .dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
  .dot.ok { background: var(--ok); } .dot.bad { background: var(--bad); }
  .pill { margin-left: auto; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.66rem; letter-spacing: 0.08em; text-transform: uppercase; padding: 0.18rem 0.55rem; border: 1px solid var(--line-strong); color: var(--text-soft); }
  .pill.ok { color: var(--ok); border-color: rgba(82, 201, 138, 0.4); }
  .pill.bad { color: var(--bad); border-color: rgba(224, 108, 108, 0.4); }
  .comp-detail { color: var(--text-dim); font-size: 0.78rem; margin-top: 0.3rem; }
  .comp-bar { display: flex; gap: 2px; margin-top: 0.7rem; height: 26px; align-items: stretch; }
  .comp-bar i { flex: 1; min-width: 1.5px; background: var(--line); border-radius: 1px; }
  .comp-bar i.up-100 { background: var(--ok); opacity: 0.85; }
  .comp-bar i.up-part { background: var(--warn); opacity: 0.9; }
  .comp-bar i.up-down { background: var(--bad); }
  .comp-bar i.nodata { background: var(--line); }
  .comp-uptime { display: flex; justify-content: space-between; color: var(--text-dim); font-size: 0.7rem; margin-top: 0.35rem; }

  .incident { border: 1px solid var(--line); border-left: 3px solid var(--line-strong); background: var(--bg-card); padding: 0.95rem 1.25rem; margin-bottom: 0.5rem; }
  .incident.bad { border-left-color: var(--bad); }
  .incident.warn { border-left-color: var(--warn); }
  .incident.info { border-left-color: var(--info); }
  .incident-head { display: flex; align-items: center; gap: 0.6rem; font-size: 0.8rem; }
  .incident-head .sev { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase; padding: 0.12rem 0.5rem; }
  .incident.bad .sev { color: var(--bad); border: 1px solid rgba(224,108,108,0.4); }
  .incident.warn .sev { color: var(--warn); border: 1px solid rgba(217,166,98,0.4); }
  .incident.info .sev { color: var(--info); border: 1px solid rgba(123,167,217,0.4); }
  .incident-head .state { margin-left: auto; color: var(--text-dim); font-size: 0.72rem; }
  .incident p { color: var(--text-soft); font-size: 0.86rem; margin-top: 0.4rem; white-space: pre-wrap; }

  footer { margin-top: 3rem; padding-top: 1.25rem; border-top: 1px solid var(--line); color: var(--text-dim); font-size: 0.75rem; display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
  footer a { color: var(--text-soft); text-decoration: none; border-bottom: 1px dotted var(--line-strong); }
  footer a:hover { color: var(--accent); }
  @media (max-width: 560px) { .hero .meta { display: none; } .comp-bar { height: 18px; } }
</style>
</head>
<body>
<div class="wrap">
  <header>
    <a class="brand" href="https://dash.atzenix.com/">atzenix<span>.</span>status</a>
    <span class="brand-sub mono">free hosting platform</span>
  </header>

  <div class="hero <?= e($overallCls) ?>">
    <span class="pulse"></span>
    <h1><?= e($overallText) ?></h1>
    <div class="meta mono">
      checked <?= $cache ? e($fmtAgo($ago($cache['generated_at']))) : 'never' ?><br>
      every 5 minutes
    </div>
  </div>
  <?php if ($stale): ?>
  <div class="incident warn" style="margin-bottom:1.5rem">
    <div class="incident-head"><span class="sev mono">monitor</span><span class="state">warning</span></div>
    <p>The monitoring agent hasn't reported recently, the data below is the last known state and may not reflect the current situation.</p>
  </div>
  <?php endif; ?>

  <h2 class="section">Components</h2>
  <?php foreach ($comps as $c): ?>
  <div class="comp">
    <div class="comp-top">
      <span class="dot <?= $c['ok'] ? 'ok' : 'bad' ?>"></span>
      <span class="comp-name"><?= e($c['name']) ?></span>
      <span class="pill <?= $c['ok'] ? 'ok' : 'bad' ?>"><?= $c['ok'] ? 'operational' : 'down' ?></span>
    </div>
    <div class="comp-detail mono"><?= e($c['detail']) ?><?= $c['latency_ms'] > 0 ? ' · ' . (int)$c['latency_ms'] . ' ms' : '' ?></div>
    <div class="comp-bar" aria-hidden="true">
      <?php foreach (array_slice($c['history'] ?? [], -90) as $d): ?>
        <?php if ($d['up'] === null): ?><i class="nodata" title="<?= e($d['d']) ?>, no data"></i>
        <?php elseif ($d['up'] >= 99.5): ?><i class="up-100" title="<?= e($d['d']) ?>, <?= e($d['up']) ?>% uptime"></i>
        <?php elseif ($d['up'] >= 80): ?><i class="up-part" title="<?= e($d['d']) ?>, <?= e($d['up']) ?>% uptime"></i>
        <?php else: ?><i class="up-down" title="<?= e($d['d']) ?>, <?= e($d['up']) ?>% uptime"></i><?php endif; ?>
      <?php endforeach; ?>
    </div>
    <div class="comp-uptime mono"><span>90 days ago</span><span><?= $c['uptime90'] !== null ? e($c['uptime90']) . '% uptime' : 'building history…' ?></span><span>today</span></div>
  </div>
  <?php endforeach; ?>

  <h2 class="section">Incidents</h2>
  <?php if (!$incidents): ?>
  <p style="color:var(--text-dim);font-size:0.85rem">No incidents in the last 14 days. <?php if ($stale): ?>(Incident data unavailable while the monitor is stale.)<?php endif; ?></p>
  <?php endif; ?>
  <?php foreach ($incidents as $i): ?>
    <?php [$label, $cls] = $sev[$i['severity']] ?? ['Notice', 'info']; ?>
  <div class="incident <?= e($cls) ?>">
    <div class="incident-head">
      <span class="sev mono"><?= e($label) ?></span>
      <span class="state mono"><?= $i['ongoing'] ? 'ongoing · since ' . e(date('M d, H:i', strtotime($i['started_at']))) : 'resolved ' . e($fmtAgo($ago($i['resolved_at'] ?? $i['started_at']))) ?></span>
    </div>
    <p><?= e($i['message']) ?></p>
  </div>
  <?php endforeach; ?>

  <h2 class="section">Announcements</h2>
  <?php if (!$announcements): ?>
  <p style="color:var(--text-dim);font-size:0.85rem">Nothing announced yet.</p>
  <?php endif; ?>
  <?php foreach ($announcements as $a): ?>
    <?php [$label, $cls] = $sev[$a['severity']] ?? ['Notice', 'info']; ?>
  <div class="incident <?= e($cls) ?>" style="border-left-width:2px">
    <div class="incident-head">
      <span class="sev mono"><?= e($label) ?></span>
      <span class="mono" style="color:var(--text-soft);font-size:0.78rem"><?= e(mb_strimwidth($a['message'], 0, 72, '…')) ?></span>
      <span class="state mono"><?= $a['active'] ? 'current' : 'archived' ?> · <?= e(date('M d, Y', strtotime($a['updated_at']))) ?></span>
    </div>
    <p style="margin-top:0.5rem"><?= e($a['message']) ?></p>
  </div>
  <?php endforeach; ?>

  <footer>
    <span>operated by atzenix · no trackers, no cookies on this page</span>
    <span class="mono"><a href="/api.json">JSON API</a> · <a href="https://dash.atzenix.com/">panel</a></span>
  </footer>
</div>
<?php
function e(?string $s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
?></body>
</html>
