package main

const dashboardTmpl = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>status dashboard</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background: #111; color: #ccc; font-family: monospace; font-size: 14px; padding: 20px; }
h1 { color: #fff; margin-bottom: 20px; font-size: 22px; }
h2 { color: #aaa; margin: 30px 0 12px; font-size: 16px; text-transform: uppercase; letter-spacing: 1px; }
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th { background: #1e1e1e; color: #888; text-align: left; padding: 8px 10px; border-bottom: 1px solid #333; }
td { padding: 8px 10px; border-bottom: 1px solid #222; vertical-align: middle; }
tr:hover td { background: #161616; }
a { color: #5af; text-decoration: none; }
a:hover { text-decoration: underline; }
.badge { display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 12px; font-weight: bold; }
.badge-ok      { background: #1a3a1a; color: #4f4; }
.badge-warn    { background: #3a2a00; color: #fa0; }
.badge-err     { background: #3a1010; color: #f44; }
.badge-disabled{ background: #222; color: #666; }
.badge-nodata  { background: #1a1a2a; color: #66a; }
.badge-online  { background: #1a3a1a; color: #4f4; }
.badge-offline { background: #222; color: #666; }
.uptime-bar { display: inline-block; width: 80px; height: 10px; background: #2a2a2a; border-radius: 3px; vertical-align: middle; margin-right: 6px; overflow: hidden; }
.uptime-fill { height: 100%; border-radius: 3px; }
.fill-ok   { background: #4f4; }
.fill-warn { background: #fa0; }
.fill-err  { background: #f44; }
.fill-none { background: #444; }
button, input[type=submit] { background: #222; color: #aaa; border: 1px solid #444; padding: 4px 10px; cursor: pointer; font-family: monospace; font-size: 13px; border-radius: 3px; }
button:hover, input[type=submit]:hover { background: #2a2a2a; color: #fff; border-color: #666; }
button.danger { border-color: #633; color: #f66; }
button.danger:hover { background: #2a1010; }
.form-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
input[type=text], input[type=url] { background: #1a1a1a; color: #ccc; border: 1px solid #444; padding: 5px 8px; font-family: monospace; font-size: 13px; border-radius: 3px; }
input[type=text]:focus, input[type=url]:focus { outline: none; border-color: #5af; }
.pct { font-size: 12px; color: #888; }
form { display: inline; }
</style>
</head>
<body>
<h1>status</h1>

<h2>Servers (24h uptime)</h2>
<table>
<tr>
  <th>URL</th>
  <th>Name</th>
  <th>Anon Name</th>
  <th>OK Checks</th>
  <th>Uptime</th>
  <th>Avg TTFB</th>
  <th>Status</th>
  <th>Actions</th>
</tr>
{{range .Servers}}
<tr>
  <td><a href="/chart/{{.ID}}">{{.URL}}</a></td>
  <td>{{.Name}}</td>
  <td style="color:#888">{{if .AnonName}}{{.AnonName}}{{else}}<span style="color:#444">—</span>{{end}}</td>
  <td>{{.Successes}}</td>
  <td>
    {{if gt .Total 0}}
      <span class="uptime-bar"><span class="uptime-fill {{if ge .UptimePct 99.0}}fill-ok{{else if ge .UptimePct 95.0}}fill-warn{{else}}fill-err{{end}}" style="width:{{printf "%.0f" .UptimePct}}%"></span></span>
      <span class="pct">{{printf "%.1f" .UptimePct}}%</span>
    {{else}}
      <span class="uptime-bar"><span class="uptime-fill fill-none" style="width:0%"></span></span>
      <span class="pct">—</span>
    {{end}}
  </td>
  <td style="color:{{if gt .AvgTTFBMS 0}}{{if le .AvgTTFBMS 200}}#5cb85c{{else if le .AvgTTFBMS 500}}#e6a817{{else}}#d9534f{{end}}{{else}}#444{{end}}">
    {{if gt .AvgTTFBMS 0}}{{.AvgTTFBMS}} ms{{else}}—{{end}}
  </td>
  <td>
    {{if eq .UptimeClass "ok"}}<span class="badge badge-ok">OK</span>
    {{else if eq .UptimeClass "warn"}}<span class="badge badge-warn">DEGRADED</span>
    {{else if eq .UptimeClass "err"}}<span class="badge badge-err">DOWN</span>
    {{else if eq .UptimeClass "disabled"}}<span class="badge badge-disabled">DISABLED</span>
    {{else}}<span class="badge badge-nodata">NO DATA</span>{{end}}
  </td>
  <td>
    {{if .Active}}
    <form method="POST" action="/servers/toggle">
      <input type="hidden" name="id" value="{{.ID}}">
      <input type="hidden" name="active" value="0">
      <button type="submit">Pause</button>
    </form>
    {{else}}
    <form method="POST" action="/servers/toggle">
      <input type="hidden" name="id" value="{{.ID}}">
      <input type="hidden" name="active" value="1">
      <button type="submit">Enable</button>
    </form>
    {{end}}
    <form method="POST" action="/servers/delete" onsubmit="return confirm('Delete server {{.URL}}?')">
      <input type="hidden" name="id" value="{{.ID}}">
      <button type="submit" class="danger">Delete</button>
    </form>
  </td>
</tr>
{{else}}
<tr><td colspan="8" style="color:#555;text-align:center;padding:20px">No servers configured</td></tr>
{{end}}
</table>

<form method="POST" action="/servers/add">
  <div class="form-row">
    <input type="url" name="url" placeholder="https://example.com" required style="width:300px">
    <input type="text" name="name" placeholder="Name (optional)" style="width:180px">
    <input type="text" name="anon_name" placeholder="Anon name (public)" style="width:180px">
  </div>
  <div class="form-row">
    <input type="number" name="expected_code" value="200" min="100" max="599" style="width:90px" title="Expected HTTP code">
    <input type="text" name="expected_body" placeholder="Expected body substring (optional)" style="width:260px">
    <label style="color:#888"><input type="checkbox" name="insecure" value="1"> insecure TLS</label>
    <input type="submit" value="Add Server">
  </div>
</form>

<h2>Agents</h2>
<table>
<tr>
  <th>Name</th>
  <th>Anon Name</th>
  <th>IP</th>
  <th>Last Seen</th>
  <th>Status</th>
  <th>Actions</th>
</tr>
{{range .Agents}}
<tr>
  <td>{{.Name}}</td>
  <td style="color:#888">{{if .AnonName}}{{.AnonName}}{{else}}<span style="color:#444">—</span>{{end}}</td>
  <td>{{if .LastIP}}{{.LastIP}}{{else}}<span style="color:#555">—</span>{{end}}</td>
  <td>{{.LastSeenStr}}</td>
  <td>
    {{if .Online}}<span class="badge badge-online">ONLINE</span>
    {{else}}<span class="badge badge-offline">OFFLINE</span>{{end}}
  </td>
  <td>
    <form method="POST" action="/agents/delete" onsubmit="return confirm('Delete agent {{.Name}}?')">
      <input type="hidden" name="id" value="{{.ID}}">
      <button type="submit" class="danger">Delete</button>
    </form>
  </td>
</tr>
{{else}}
<tr><td colspan="6" style="color:#555;text-align:center;padding:20px">No agents registered</td></tr>
{{end}}
</table>

<form method="POST" action="/agents/add">
  <div class="form-row">
    <input type="text" name="name" placeholder="Agent name" required style="width:200px">
    <input type="text" name="anon_name" placeholder="Anon name (public)" style="width:180px">
    <input type="submit" value="Add Agent">
  </div>
</form>

</body>
</html>`

const tokenTmpl = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Agent Created — status</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background: #111; color: #ccc; font-family: monospace; font-size: 14px; padding: 40px; }
h1 { color: #fff; margin-bottom: 24px; }
.token-box { background: #1a1a1a; border: 1px solid #444; border-radius: 6px; padding: 24px; max-width: 640px; }
.token-label { color: #888; margin-bottom: 8px; }
.token-value { font-size: 15px; color: #5af; word-break: break-all; background: #0d0d0d; padding: 12px; border-radius: 4px; border: 1px solid #333; margin-bottom: 16px; }
.warning { background: #2a1a00; border: 1px solid #664400; color: #fa0; padding: 12px; border-radius: 4px; margin-bottom: 20px; line-height: 1.5; }
a { color: #5af; text-decoration: none; }
a:hover { text-decoration: underline; }
.agent-name { color: #fff; font-size: 16px; margin-bottom: 20px; }
</style>
</head>
<body>
<h1>Agent Created</h1>
<div class="token-box">
  <div class="agent-name">Agent: {{index . "Name"}}</div>
  <div class="warning">
    &#9888; Save this token now — it will NOT be shown again.<br>
    Set it as the AGENT_TOKEN environment variable on the agent host.
  </div>
  <div class="token-label">Agent Token:</div>
  <div class="token-value">{{index . "Token"}}</div>
  <a href="/">&larr; Back to dashboard</a>
</div>
</body>
</html>`

const publicTmpl = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Status</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background: #111; color: #ccc; font-family: monospace; font-size: 14px; padding: 20px; }
h1 { color: #fff; margin-bottom: 20px; font-size: 22px; }
h2 { color: #aaa; margin: 30px 0 12px; font-size: 16px; text-transform: uppercase; letter-spacing: 1px; }
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th { background: #1e1e1e; color: #888; text-align: left; padding: 8px 10px; border-bottom: 1px solid #333; }
td { padding: 8px 10px; border-bottom: 1px solid #222; vertical-align: middle; }
tr:hover td { background: #161616; }
.badge { display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 12px; font-weight: bold; }
.badge-ok      { background: #1a3a1a; color: #4f4; }
.badge-warn    { background: #3a2a00; color: #fa0; }
.badge-err     { background: #3a1010; color: #f44; }
.badge-nodata  { background: #1a1a2a; color: #66a; }
.badge-online  { background: #1a3a1a; color: #4f4; }
.badge-offline { background: #222; color: #666; }
.uptime-bar { display: inline-block; width: 80px; height: 10px; background: #2a2a2a; border-radius: 3px; vertical-align: middle; margin-right: 6px; overflow: hidden; }
.uptime-fill { height: 100%; border-radius: 3px; }
.fill-ok   { background: #4f4; }
.fill-warn { background: #fa0; }
.fill-err  { background: #f44; }
.fill-none { background: #444; }
.pct { font-size: 12px; color: #888; }
</style>
</head>
<body>
<h1>Status</h1>

<h2>Services (24h)</h2>
<table>
<tr>
  <th>Name</th>
  <th>OK Checks</th>
  <th>Uptime</th>
  <th>Avg TTFB</th>
  <th>Status</th>
</tr>
{{range .Servers}}
<tr>
  <td>{{.AnonName}}</td>
  <td>{{.Successes}}</td>
  <td>
    {{if gt .Successes 0}}
      <span class="uptime-bar"><span class="uptime-fill {{if ge .UptimePct 99.0}}fill-ok{{else if ge .UptimePct 95.0}}fill-warn{{else}}fill-err{{end}}" style="width:{{printf "%.0f" .UptimePct}}%"></span></span>
      <span class="pct">{{printf "%.1f" .UptimePct}}%</span>
    {{else}}
      <span class="uptime-bar"><span class="uptime-fill fill-none" style="width:0%"></span></span>
      <span class="pct">—</span>
    {{end}}
  </td>
  <td style="color:{{if gt .AvgTTFBMS 0}}{{if le .AvgTTFBMS 200}}#5cb85c{{else if le .AvgTTFBMS 500}}#e6a817{{else}}#d9534f{{end}}{{else}}#444{{end}}">
    {{if gt .AvgTTFBMS 0}}{{.AvgTTFBMS}} ms{{else}}—{{end}}
  </td>
  <td>
    {{if eq .UptimeClass "ok"}}<span class="badge badge-ok">OK</span>
    {{else if eq .UptimeClass "warn"}}<span class="badge badge-warn">DEGRADED</span>
    {{else if eq .UptimeClass "err"}}<span class="badge badge-err">DOWN</span>
    {{else}}<span class="badge badge-nodata">NO DATA</span>{{end}}
  </td>
</tr>
{{else}}
<tr><td colspan="5" style="color:#555;text-align:center;padding:20px">No data available</td></tr>
{{end}}
</table>

<h2>Nodes</h2>
<table>
<tr>
  <th>Name</th>
  <th>Status</th>
</tr>
{{range .Agents}}
<tr>
  <td>{{.AnonName}}</td>
  <td>
    {{if .Online}}<span class="badge badge-online">ONLINE</span>
    {{else}}<span class="badge badge-offline">OFFLINE</span>{{end}}
  </td>
</tr>
{{else}}
<tr><td colspan="2" style="color:#555;text-align:center;padding:20px">No nodes</td></tr>
{{end}}
</table>

</body>
</html>`

const chartTmpl = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Server.URL}} — status</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { background: #111; color: #ccc; font-family: monospace; font-size: 14px; padding: 20px; }
h1 { color: #fff; margin-bottom: 4px; font-size: 18px; word-break: break-all; }
.subtitle { color: #666; margin-bottom: 20px; font-size: 13px; }
a { color: #5af; text-decoration: none; }
a:hover { text-decoration: underline; }
.controls { margin-bottom: 20px; display: flex; gap: 8px; align-items: center; }
.controls span { color: #888; margin-right: 4px; }
button { background: #222; color: #aaa; border: 1px solid #444; padding: 4px 12px; cursor: pointer; font-family: monospace; font-size: 13px; border-radius: 3px; }
button:hover { background: #2a2a2a; color: #fff; border-color: #666; }
button.active { background: #1a2a3a; color: #5af; border-color: #5af; }
.chart-container { background: #151515; border: 1px solid #222; border-radius: 6px; padding: 16px; margin-bottom: 20px; }
.chart-title { color: #888; font-size: 12px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 12px; }
canvas { max-height: 220px; }
.back { margin-top: 10px; }
#status { color: #666; font-size: 12px; margin-left: 12px; }
</style>
</head>
<body>
<div class="back"><a href="/">&larr; Dashboard</a></div>
<br>
<h1>{{.Server.URL}}</h1>
<div class="subtitle">{{if .Server.Name}}{{.Server.Name}}{{else}}(no name){{end}}</div>

<div class="controls">
  <span>Range:</span>
  <button onclick="load(6)"   id="btn6">6h</button>
  <button onclick="load(24)"  id="btn24" class="active">24h</button>
  <button onclick="load(48)"  id="btn48">48h</button>
  <button onclick="load(168)" id="btn168">7d</button>
  <span style="color:#555; margin: 0 4px 0 8px">|</span>
  <span>Agent:</span>
  <select id="agentSel" onchange="load(currentHours)" style="background:#222;color:#aaa;border:1px solid #444;padding:4px 8px;font-family:monospace;font-size:13px;border-radius:3px;cursor:pointer">
    <option value="0">all</option>
    {{range .Agents}}<option value="{{.ID}}">{{.Name}}{{if .LastIP}} ({{.LastIP}}){{end}}</option>{{end}}
  </select>
  <span id="status"></span>
</div>

<div class="chart-container">
  <div class="chart-title">Availability</div>
  <canvas id="availChart"></canvas>
</div>
<div class="chart-container">
  <div class="chart-title">Response Time (ms)</div>
  <canvas id="rtChart"></canvas>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script>
const serverID = {{.Server.ID}};
const agentNames = {0: 'all', {{range .Agents}}{{.ID}}: '{{.Name}}', {{end}}};
const darkColor = '#333';
const gridColor = '#1e1e1e';

const availCtx = document.getElementById('availChart').getContext('2d');
const rtCtx = document.getElementById('rtChart').getContext('2d');

const availChart = new Chart(availCtx, {
  type: 'scatter',
  data: { datasets: [
    { label: 'Success', data: [], backgroundColor: '#4f4', pointRadius: 4 },
    { label: 'Failure', data: [], backgroundColor: '#f44', pointRadius: 4 },
  ]},
  options: {
    animation: false,
    plugins: {
      legend: { labels: { color: '#888', font: { family: 'monospace' } } },
      tooltip: {
        callbacks: {
          label: ctx => {
            const p = ctx.raw;
            const name = agentNames[p.aid] || ('agent ' + p.aid);
            return name + '  ' + new Date(p.x).toLocaleTimeString();
          },
          title: () => '',
        },
      },
    },
    scales: {
      x: {
        type: 'time',
        time: { tooltipFormat: 'yyyy-MM-dd HH:mm' },
        ticks: { color: '#666', maxTicksLimit: 10 },
        grid: { color: gridColor },
      },
      y: {
        min: -0.1, max: 1.1,
        ticks: {
          color: '#666',
          callback: v => v === 1 ? 'OK' : v === 0 ? 'FAIL' : '',
          stepSize: 1,
        },
        grid: { color: gridColor },
      },
    },
  },
});

const rtChart = new Chart(rtCtx, {
  type: 'line',
  data: { datasets: [
    { label: 'Total ms', data: [], borderColor: '#5af', backgroundColor: 'transparent', pointRadius: 2, tension: 0.2 },
    { label: 'TTFB ms',  data: [], borderColor: '#fa0', backgroundColor: 'transparent', pointRadius: 2, tension: 0.2 },
  ]},
  options: {
    animation: false,
    plugins: { legend: { labels: { color: '#888', font: { family: 'monospace' } } } },
    scales: {
      x: {
        type: 'time',
        time: { tooltipFormat: 'yyyy-MM-dd HH:mm' },
        ticks: { color: '#666', maxTicksLimit: 10 },
        grid: { color: gridColor },
      },
      y: {
        ticks: { color: '#666' },
        grid: { color: gridColor },
        title: { display: true, text: 'ms', color: '#666' },
      },
    },
  },
});

let currentHours = 24;

async function load(hours) {
  currentHours = hours;
  [6,24,48,168].forEach(h => {
    const btn = document.getElementById('btn'+h);
    btn.className = h === hours ? 'active' : '';
  });
  const status = document.getElementById('status');
  status.textContent = 'Loading...';
  try {
    const agentID = document.getElementById('agentSel').value;
    const resp = await fetch('/api/chart-data/' + serverID + '?hours=' + hours + '&agent=' + agentID);
    if (!resp.ok) throw new Error('HTTP ' + resp.status);
    const data = await resp.json();
    status.textContent = (data ? data.length : 0) + ' points';

    const successPts = [], failPts = [], totalPts = [], ttfbPts = [];
    (data || []).forEach(p => {
      const t = new Date(p.t);
      if (p.s) {
        successPts.push({ x: t, y: 1, aid: p.aid });
      } else {
        failPts.push({ x: t, y: 0, aid: p.aid });
      }
      if (p.ms > 0) totalPts.push({ x: t, y: p.ms });
      if (p.ttfb > 0) ttfbPts.push({ x: t, y: p.ttfb });
    });

    availChart.data.datasets[0].data = successPts;
    availChart.data.datasets[1].data = failPts;
    availChart.update();

    rtChart.data.datasets[0].data = totalPts;
    rtChart.data.datasets[1].data = ttfbPts;
    rtChart.update();
  } catch(e) {
    status.textContent = 'Error: ' + e.message;
  }
}

load(24);
</script>
</body>
</html>`
