/**
 * DaemonTab — the Zeq Audit Daemon inside the extension panel.
 *
 * The daemon spawns SERVER-SIDE source agents on your machine that stream
 * events into the entangled state (Observer) — persistent, surviving browser
 * close. Where the oracle is a client-side watcher (runs while the panel is
 * open), the daemon is its server-side big brother:
 *   • http_webhook   — gives you a URL + a copy-paste snippet to drop into ANY
 *                      website/app; every POST becomes an audited transition.
 *   • generic_polling — the daemon polls any URL on a Zeqond cadence (a
 *                      server-side oracle — no browser needed).
 *   • filesystem_watch, mongo/postgres/s3/mqtt/redis/kafka — infra sources.
 *
 * All calls go through the service worker (session-token auth, no CORS).
 *
 * @version 1.287.10
 * @license CC BY 4.0 — Zeq. H / Zeq 1.287 Hz Limited
 */
const DaemonTab = (() => {
  "use strict";

  let _cid = null, _origin = "", _slug = "", _lastSpawn = null, _timer = null;

  // Browser-relevant defaults first; the rest are infra sources.
  const TYPES = [
    "http_webhook", "generic_polling", "filesystem_watch", "mongo_change_stream",
    "postgres_logical", "s3_notification", "mqtt", "redis_keyspace", "kafka_consumer",
  ];
  const DEFAULTS = {
    http_webhook: {},  // open intake (no secret). Add a ≥8-char `secret` to HMAC-authenticate.
    generic_polling: { url: "https://example.com/status.json", intervalZeqonds: 10, emitOn: "change" },
    filesystem_watch: { path: "/var/log", recursive: true, debounceMs: 250 },
    mongo_change_stream: { uri: "mongodb://localhost:27017", db: "mydb", collections: ["orders"], fullDocument: "updateLookup" },
    postgres_logical: { uri: "postgres://user:pass@localhost:5432/mydb", channel: "data_change" },
    s3_notification: { region: "eu-west-2", queueUrl: "https://sqs.eu-west-2.amazonaws.com/123/uploads" },
    mqtt: { url: "mqtt://broker.local:1883", topics: ["sensors/+"], qos: 0 },
    redis_keyspace: { url: "redis://localhost:6379", patterns: ["__keyspace@0__:*"] },
    kafka_consumer: { brokers: ["kafka1:9092"], groupId: "zeq-audit", topics: ["events"] },
  };
  const BLURB = {
    http_webhook: "Get a URL + snippet to embed in any site/app — every POST is an audited event.",
    generic_polling: "The daemon polls a URL server-side on a Zeqond cadence (a hosted oracle).",
    filesystem_watch: "Watch a directory on the daemon host for file changes.",
    mongo_change_stream: "Stream MongoDB change events.",
    postgres_logical: "Listen on a Postgres LISTEN/NOTIFY channel.",
    s3_notification: "Consume S3 upload notifications from an SQS queue.",
    mqtt: "Subscribe to MQTT topics.",
    redis_keyspace: "Watch Redis keyspace notifications.",
    kafka_consumer: "Consume from Kafka topics.",
  };

  function esc(s) { return String(s == null ? "" : s).replace(/[&<>"]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }[c])); }
  function sw(msg) { return new Promise((res) => { try { chrome.runtime.sendMessage(msg, (r) => res(chrome.runtime.lastError ? null : r)); } catch (_) { res(null); } }); }
  function authed() { return typeof ZeqAuth !== "undefined" && ZeqAuth.isAuthenticated(); }

  const STYLE = "<style>" +
    ".zd{padding:12px;overflow-y:auto;height:100%}" +
    ".zd h3{font-size:13px;margin:0 0 3px;color:var(--text-primary)}" +
    ".zd .lead{font-size:11px;color:var(--text-muted);line-height:1.5;margin:0 0 10px}" +
    ".zd .card{border:1px solid var(--border);border-radius:9px;padding:10px;margin-bottom:9px;background:var(--bg-secondary)}" +
    ".zd label{font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted);display:block;margin:6px 0 3px}" +
    ".zd select,.zd input,.zd textarea{width:100%;padding:7px 9px;background:rgba(0,0,0,.45);border:1px solid var(--border);border-radius:7px;color:var(--text-primary);font-size:12px;outline:none;font-family:inherit}" +
    ".zd textarea{font-family:'JetBrains Mono',monospace;font-size:11px;min-height:64px;resize:vertical}" +
    ".zd select:focus,.zd input:focus,.zd textarea:focus{border-color:var(--accent-mint)}" +
    ".zd .blurb{font-size:10.5px;color:var(--text-secondary);margin:5px 0 0;line-height:1.45}" +
    ".zd .btn{width:100%;margin-top:9px;padding:9px;border-radius:8px;border:1px solid var(--accent-mint);background:var(--accent-mint);color:#02120a;font-weight:700;font-size:12px;cursor:pointer}" +
    ".zd .btn.sec{background:transparent;color:var(--text-primary);border-color:var(--border);font-weight:600}" +
    ".zd .btn:disabled{opacity:.5}" +
    ".zd pre{background:rgba(0,0,0,.5);border:1px solid var(--border);border-radius:7px;padding:8px;font-size:10px;color:#00d4ff;white-space:pre-wrap;word-break:break-all;margin:6px 0 0;font-family:'JetBrains Mono',monospace}" +
    ".zd .copy{font-size:10px;padding:4px 9px;border-radius:6px;border:1px solid var(--border);background:transparent;color:var(--accent-mint);cursor:pointer;margin-top:5px}" +
    ".zd .msg{font-size:11px;margin-top:7px;min-height:14px}.zd .ok{color:var(--accent-mint)}.zd .err{color:#ff5577}" +
    ".zd table{width:100%;border-collapse:collapse;font-size:11px;margin-top:4px}" +
    ".zd th{text-align:left;color:var(--text-muted);font-weight:600;font-size:9.5px;text-transform:uppercase;letter-spacing:.05em;padding:4px}" +
    ".zd td{padding:5px 4px;border-top:1px solid var(--border);color:var(--text-secondary);vertical-align:middle}" +
    ".zd .tag{font-size:9px;padding:2px 6px;border-radius:5px;font-weight:700}" +
    ".zd .alive{background:rgba(0,255,136,.14);color:var(--accent-mint)}.zd .dead{background:rgba(255,120,120,.14);color:#ff8a8a}" +
    ".zd .mini{font-size:9px;padding:2px 6px;border-radius:5px;border:1px solid var(--border);background:transparent;color:var(--text-secondary);cursor:pointer;margin-right:3px}" +
    ".zd .mini:hover{border-color:var(--accent-mint);color:var(--accent-mint)}" +
    ".zd .empty{font-size:11px;color:var(--text-muted);line-height:1.5}" +
    "</style>";

  function snippet(agentId) {
    const url = _origin + "/api/zeq/audit-source/" + agentId + "/event";
    return "fetch(" + JSON.stringify(url) + ", {\n" +
      "  method: 'POST',\n" +
      "  headers: { 'Content-Type': 'application/json' },\n" +
      "  body: JSON.stringify({ event: 'page_view', url: location.href, ts: Date.now() })\n" +
      "});";
  }

  function render(agents) {
    const c = document.getElementById(_cid);
    if (!c) return;
    if (!authed()) { c.innerHTML = STYLE + '<div class="zd"><div class="empty">Sign in to run audit-daemon agents on your machine.</div></div>'; return; }
    const t = (c.__type) || "http_webhook";
    const cfg = (c.__cfg != null) ? c.__cfg : JSON.stringify(DEFAULTS[t], null, 2);
    const rows = (agents || []).map((a) =>
      "<tr><td>" + esc(a.source_type) + "</td><td>" + esc(a.display_name || a.zid || "") + "</td><td>" + (a.events_seen || 0) + "</td>" +
      '<td><span class="tag ' + (a.alive ? "alive" : "dead") + '">' + (a.alive ? "ALIVE" : "OFF") + "</span></td>" +
      '<td><button class="mini" data-act="sweep" data-id="' + esc(a.agent_id) + '">Sweep</button>' +
      '<button class="mini" data-act="kill" data-id="' + esc(a.agent_id) + '">Kill</button>' +
      '<button class="mini" data-act="hook" data-id="' + esc(a.agent_id) + '" data-type="' + esc(a.source_type) + '">Install</button></td></tr>'
    ).join("");

    c.innerHTML = STYLE + '<div class="zd">' +
      "<h3>Audit Daemon</h3>" +
      '<p class="lead">Spawn a server-side agent that streams events into your machine’s Observer. Persistent — it keeps running after you close the browser.</p>' +
      '<div class="card">' +
        '<label>Source type</label><select id="zd-type">' +
          TYPES.map((x) => '<option value="' + x + '"' + (x === t ? " selected" : "") + ">" + x + "</option>").join("") + "</select>" +
        '<p class="blurb" id="zd-blurb">' + esc(BLURB[t] || "") + "</p>" +
        '<label>Name (optional)</label><input id="zd-name" placeholder="e.g. orders webhook" />' +
        "<label>Config (JSON)</label><textarea id=\"zd-cfg\">" + esc(cfg) + "</textarea>" +
        '<button class="btn" id="zd-spawn">Spawn agent → Observer</button>' +
        '<div class="msg" id="zd-msg"></div>' +
        '<div id="zd-install"></div>' +
      "</div>" +
      '<div class="card"><label>Your agents</label>' +
        (rows ? '<table><thead><tr><th>Type</th><th>Name</th><th>Events</th><th>State</th><th></th></tr></thead><tbody>' + rows + "</tbody></table>"
              : '<div class="empty">No agents yet. Spawn one above — a webhook gives you a URL to drop into any site.</div>') +
        (_origin ? '<button class="btn sec" id="zd-observer" style="margin-top:8px">Open Observer</button>' : "") +
      "</div></div>";

    wire(c);
    if (_lastSpawn) showInstall(_lastSpawn.agentId, _lastSpawn.type);
  }

  function showInstall(agentId, type) {
    const host = document.getElementById("zd-install");
    if (!host) return;
    if (type === "http_webhook") {
      const url = _origin + "/api/zeq/audit-source/" + agentId + "/event";
      host.innerHTML =
        '<p class="blurb" style="margin-top:9px"><b style="color:var(--accent-mint)">Install on any website or app</b> — point a webhook at this URL, or paste the snippet into your page:</p>' +
        '<pre id="zd-url">POST ' + esc(url) + "</pre>" +
        '<button class="copy" data-copy="zd-url">Copy URL</button>' +
        '<pre id="zd-snip">' + esc(snippet(agentId)) + "</pre>" +
        '<button class="copy" data-copy="zd-snip">Copy snippet</button>';
    } else {
      host.innerHTML = '<p class="blurb" style="margin-top:9px"><b style="color:var(--accent-mint)">Agent running.</b> Events stream into your Observer as they arrive.</p>';
    }
    host.querySelectorAll("[data-copy]").forEach((b) => b.addEventListener("click", () => {
      const el = document.getElementById(b.getAttribute("data-copy"));
      const txt = (el.textContent || "").replace(/^POST /, "");
      if (navigator.clipboard) navigator.clipboard.writeText(txt).then(() => { const o = b.textContent; b.textContent = "✓ copied"; setTimeout(() => { b.textContent = o; }, 1400); });
    }));
  }

  function wire(c) {
    const typeSel = document.getElementById("zd-type");
    const cfgEl = document.getElementById("zd-cfg");
    if (typeSel) typeSel.addEventListener("change", () => {
      c.__type = typeSel.value; c.__cfg = JSON.stringify(DEFAULTS[typeSel.value] || {}, null, 2);
      _lastSpawn = null; render(_agentsCache);
    });
    if (cfgEl) cfgEl.addEventListener("input", () => { c.__cfg = cfgEl.value; });
    const spawnBtn = document.getElementById("zd-spawn");
    if (spawnBtn) spawnBtn.addEventListener("click", () => doSpawn(c));
    const obs = document.getElementById("zd-observer");
    if (obs) obs.addEventListener("click", () => { try { window.open(_origin + "/state/?slug=" + encodeURIComponent(_slug), "_blank"); } catch (_) {} });
    c.querySelectorAll(".mini[data-act]").forEach((b) => b.addEventListener("click", async () => {
      const id = b.getAttribute("data-id"), act = b.getAttribute("data-act");
      if (act === "hook") { _lastSpawn = { agentId: id, type: b.getAttribute("data-type") }; showInstall(id, b.getAttribute("data-type")); return; }
      if (act === "kill" && !confirm("Stop this agent?")) return;
      b.disabled = true;
      const r = await sw({ type: "daemonAction", agentId: id, action: act });
      msg(r && r.success ? (act === "kill" ? "Agent stopped." : "Swept.") : ("Action failed: " + ((r && r.error) || "?")), r && r.success);
      load();
    }));
  }

  function msg(text, ok) { const el = document.getElementById("zd-msg"); if (el) { el.className = "msg " + (ok ? "ok" : "err"); el.textContent = text; } }

  async function doSpawn(c) {
    const typeSel = document.getElementById("zd-type"), nameEl = document.getElementById("zd-name"), cfgEl = document.getElementById("zd-cfg");
    let cfg; try { cfg = JSON.parse(cfgEl.value || "{}"); } catch (e) { msg("Config is not valid JSON: " + e.message, false); return; }
    // Empty webhook secret is rejected server-side ("≥8 chars when set"); drop it for an open intake.
    if (typeof cfg.secret === "string" && cfg.secret.length < 8) delete cfg.secret;
    const btn = document.getElementById("zd-spawn"); btn.disabled = true; btn.textContent = "Spawning…";
    const r = await sw({ type: "daemonSpawn", source_type: typeSel.value, source_config: cfg, display_name: nameEl.value || undefined });
    btn.disabled = false; btn.textContent = "Spawn agent → Observer";
    if (!r || !r.success) { msg("Spawn failed: " + ((r && r.error) || "?"), false); return; }
    _origin = r.origin || _origin;
    const d = r.data || {};
    const agentId = d.agentId || d.agent_id || d.id || (d.agent && d.agent.agent_id);
    msg("✓ Spawned " + (d.zid || agentId || "agent"), true);
    _lastSpawn = { agentId, type: typeSel.value };
    showInstall(agentId, typeSel.value);
    load();
  }

  let _agentsCache = [];
  async function load() {
    const r = await sw({ type: "daemonList" });
    if (r && r.success) { _origin = r.origin || _origin; _slug = r.slug || _slug; _agentsCache = (r.data && r.data.agents) || []; }
    render(_agentsCache);
  }

  function init(cid) {
    _cid = cid;
    render(_agentsCache);
    load();
    if (_timer) clearInterval(_timer);
    _timer = setInterval(() => { const t = document.getElementById("tab-daemon"); if (t && t.classList.contains("active")) load(); }, 6000);
  }
  function stop() { if (_timer) { clearInterval(_timer); _timer = null; } }

  return { init, stop };
})();
if (typeof module !== "undefined" && module.exports) { module.exports = DaemonTab; }
