<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>broad-announce · DLQ</title>
<style>
  :root { color-scheme: light dark; }
  body {
    font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
    margin: 0; padding: 24px;
    background: #fafafa; color: #111;
  }
  @media (prefers-color-scheme: dark) {
    body { background: #0d0f12; color: #e4e4e4; }
    table { border-color: #2a2e35; }
    th { background: #161a20; }
    tr:nth-child(even) { background: #131820; }
    a, a:visited { color: #6ea8fe; }
    .filters { background: #161a20; border-color: #2a2e35; }
  }
  h1 { margin: 0 0 12px; font-size: 22px; font-weight: 600; }
  .sub { color: #6b6b6b; font-size: 13px; margin-bottom: 16px; }
  .filters {
    display: flex; gap: 8px; align-items: end; flex-wrap: wrap;
    padding: 10px; border: 1px solid #ddd; border-radius: 6px; margin-bottom: 16px;
  }
  .filters label { display: flex; flex-direction: column; font-size: 12px; }
  .filters input { padding: 4px 6px; font-size: 13px; min-width: 140px; }
  .filters button { padding: 5px 12px; font-size: 13px; }
  table { width: 100%; border-collapse: collapse; font-size: 13px; }
  th, td { padding: 6px 8px; border-bottom: 1px solid #eee; text-align: left; vertical-align: top; }
  th { background: #f3f3f3; font-weight: 600; }
  td.id { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: #888; }
  td.err { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; max-width: 280px; word-break: break-all; }
  td.actions { white-space: nowrap; }
  .btn { padding: 3px 9px; font-size: 12px; border-radius: 4px; border: 1px solid #888; background: transparent; cursor: pointer; color: inherit; }
  .btn:hover { background: rgba(0,0,0,.06); }
  .btn-primary { border-color: #2e7d32; color: #2e7d32; }
  .btn-primary:hover { background: rgba(46,125,50,.1); }
  .btn-danger { border-color: #b71c1c; color: #b71c1c; }
  .btn-danger:hover { background: rgba(183,28,28,.1); }
  .pill { display: inline-block; padding: 1px 6px; border-radius: 10px; font-size: 11px; background: #eee; color: #555; }
  .empty { padding: 40px; text-align: center; color: #888; font-style: italic; }
  .nav { margin-top: 12px; font-size: 12px; }
  .nav a { color: #1976d2; text-decoration: none; margin-right: 8px; }
  .nav a:hover { text-decoration: underline; }
  details { margin-top: 4px; }
  details pre {
    font-family: ui-monospace, monospace; font-size: 11px; max-width: 480px;
    max-height: 200px; overflow: auto; padding: 6px; background: rgba(0,0,0,.04); border-radius: 3px;
  }
  .toast {
    position: fixed; bottom: 16px; right: 16px; padding: 10px 14px;
    background: #323232; color: #fff; border-radius: 4px;
    font-size: 13px; opacity: 0; transition: opacity .2s;
    pointer-events: none;
  }
  .toast.show { opacity: 1; }
  .toast.error { background: #b71c1c; }
</style>
</head>
<body>
<h1>broad-announce · DLQ</h1>
<p class="sub">
  {{- if .HasFilters }}
  Filtered:
    {{- if .Filters.CompanyID }} <span class="pill">company={{.Filters.CompanyID}}</span>{{- end }}
    {{- if .Filters.Channel }}   <span class="pill">channel={{.Filters.Channel}}</span>{{- end }}
    {{- if .Filters.AlertID }}   <span class="pill">alert={{.Filters.AlertID}}</span>{{- end }}
  ·
  {{- end }}
  {{if .ShowAll}}showing all (incl. discarded){{else}}hiding discarded{{end}} · last 30d · {{len .Rows}} row(s)
</p>

<form class="filters" method="get" action="/dlq">
  <label>company_id
    <input type="text" name="company_id" value="{{.Filters.CompanyID}}">
  </label>
  <label>channel
    <input type="text" name="channel" value="{{.Filters.Channel}}">
  </label>
  <label>alert_id
    <input type="text" name="alert_id" value="{{.Filters.AlertID}}">
  </label>
  <label style="flex-direction:row;align-items:center;gap:4px">
    <input type="checkbox" name="include" value="all" {{if .ShowAll}}checked{{end}}> show discarded
  </label>
  <button type="submit">Apply</button>
  <a href="/dlq" class="btn">Reset</a>
</form>

{{if .Rows}}
<table>
  <thead>
    <tr>
      <th>id</th>
      <th>created</th>
      <th>company</th>
      <th>channel</th>
      <th>alert</th>
      <th>individual</th>
      <th>attempts</th>
      <th>last error</th>
      <th>actions</th>
    </tr>
  </thead>
  <tbody>
  {{range .Rows}}
    <tr>
      <td class="id">#{{.ID}}</td>
      <td>{{.CreatedAt.Format "2006-01-02 15:04:05 UTC"}}</td>
      <td>{{.CompanyID}}</td>
      <td><span class="pill">{{.Channel}}</span></td>
      <td class="id">{{.AlertID}}</td>
      <td class="id">{{.IndividualID}}</td>
      <td>{{.Attempts}}</td>
      <td class="err">{{.LastError}}</td>
      <td class="actions">
        {{if not .Discarded}}
          <button class="btn btn-primary" onclick="dlqAction({{.ID}}, 'replay', this)">replay</button>
          <button class="btn btn-danger"  onclick="dlqAction({{.ID}}, 'discard', this)">discard</button>
        {{else}}
          <span class="pill">discarded{{if .DiscardedBy}} by {{.DiscardedBy}}{{end}}</span>
        {{end}}
        <a class="btn" href="/v1/dlq/{{.ID}}" target="_blank">json</a>
      </td>
    </tr>
  {{end}}
  </tbody>
</table>
{{else}}
<div class="empty">No DLQ rows match the current filters. 🎉</div>
{{end}}

<div class="nav">
  <a href="/v1/dlq?limit=100">raw JSON</a> ·
  <a href="/metrics">metrics</a> ·
  <a href="/v1/ping">ping</a>
</div>

<div id="toast" class="toast"></div>

<script>
function showToast(msg, isError) {
  var t = document.getElementById("toast");
  t.textContent = msg;
  t.className = "toast show" + (isError ? " error" : "");
  setTimeout(function() { t.className = "toast"; }, 2400);
}
function dlqAction(id, action, btn) {
  if (!confirm(action + " DLQ row #" + id + "?")) return;
  btn.disabled = true;
  fetch("/v1/dlq/" + id + "/" + action, { method: "POST" })
    .then(function(r) {
      if (!r.ok) {
        return r.text().then(function(t) {
          throw new Error("HTTP " + r.status + ": " + t);
        });
      }
      return r.json();
    })
    .then(function(j) {
      showToast(action + " #" + id + " ok", false);
      setTimeout(function() { location.reload(); }, 600);
    })
    .catch(function(e) {
      showToast("error: " + e.message, true);
      btn.disabled = false;
    });
}
</script>
</body>
</html>
