/**
 * Zeq Connector — inject a state-contract ORACLE into any website.
 *
 * Injected on demand into the page the user is on. Lets them pick a value on
 * the page to watch; it deploys (or REUSES — oracles are unique per target) an
 * oracle state-contract on their machine, then auto-reads that value on a
 * Zeqond cadence, firing a contract transition for each reading — so the data
 * streams into the machine's Observer (entangled state), where it can drive
 * other contracts, webhooks, and alerts.
 *
 * This is the framework expanding into the whole web: connect your ZeqVM state
 * machine to ANY website, application, or software — price feeds, stock levels,
 * shipment status, logistics counters, dashboards, anything with a value.
 *
 * Surface rule: no "seconds" on user surfaces — cadence is shown in Zeqonds
 * (1 Zeqond = 0.777 s). The timer converts internally.
 *
 * @version 1.287.7
 * @license CC BY 4.0 — Zeq. H / Zeq 1.287 Hz Limited
 */
(() => {
  "use strict";
  if (document.getElementById("zeq-connector-root")) { document.getElementById("zeq-connector-root").remove(); return; }

  const TAU_S = 0.777000777; // 1 Zeqond in seconds (display constant)

  const root = document.createElement("div");
  root.id = "zeq-connector-root";
  root.style.cssText = "position:fixed;top:16px;right:16px;z-index:2147483647;";
  const shadow = root.attachShadow({ mode: "open" });
  shadow.innerHTML = `
    <style>
      :host,*{box-sizing:border-box;}
      .w{width:328px;background:#05080d;color:#e8f5ee;border:1px solid #14301f;border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.6);font-family:-apple-system,Inter,system-ui,sans-serif;overflow:hidden;}
      .bar{display:flex;align-items:center;gap:8px;padding:9px 11px;background:#0a1410;cursor:move;user-select:none;border-bottom:1px solid #14301f;}
      .mark{font-family:'JetBrains Mono',ui-monospace,monospace;font-weight:800;font-size:13px;background:linear-gradient(135deg,#fff,#00ff88);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;}
      .zid{font-size:10px;color:#4d6b59;font-family:'JetBrains Mono',monospace;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
      .x{background:none;border:none;color:#7fa791;cursor:pointer;font-size:15px;line-height:1;}
      .body{padding:11px;}
      .lead{font-size:11px;color:#8fb8a2;line-height:1.5;margin:0 0 9px;}
      .h{font-size:10px;letter-spacing:.09em;text-transform:uppercase;color:#4d6b59;margin:2px 0 6px;}
      .host{font-size:11px;color:#7fa791;margin-bottom:9px;word-break:break-all;}.host b{color:#00ff88;}
      .in{width:100%;padding:8px 10px;background:rgba(0,0,0,.5);border:1px solid #14301f;border-radius:8px;color:#e8f5ee;font-size:12px;outline:none;margin-bottom:7px;}
      .in:focus{border-color:#00ff88;}
      .row{display:flex;gap:7px;}
      .row .in{margin-bottom:7px;}
      .btn{flex:1;padding:9px;border-radius:8px;border:1px solid #00ff88;background:#00ff88;color:#02120a;font-weight:700;font-size:12px;cursor:pointer;margin-bottom:7px;}
      .btn.sec{background:transparent;color:#e8f5ee;border-color:#14301f;}
      .btn:disabled{opacity:.5;}
      .val{font-family:'JetBrains Mono',monospace;font-size:12px;color:#00d4ff;word-break:break-all;background:rgba(0,0,0,.45);border:1px solid #14301f;border-radius:6px;padding:6px 8px;margin-bottom:7px;min-height:28px;}
      .out{font-size:11px;color:#8fb8a2;line-height:1.5;margin-top:4px;}.out a{color:#00ff88;}
      .ok{color:#00ff88;}.err{color:#ff5577;}
      .signin{font-size:11px;color:#8fb8a2;line-height:1.5;}
      label.fl{font-size:10px;color:#4d6b59;display:block;margin:0 0 3px;}
    </style>
    <div class="w">
      <div class="bar" id="bar"><span class="mark">ZeqVM oracle</span><span class="zid" id="zid">connecting…</span><button class="x" id="x">✕</button></div>
      <div class="body" id="body">
        <p class="lead">Watch any value on this page. Each reading records to your machine's Observer as a contract transition — connect logistics, prices, stock, status from any site into your state machine.</p>
        <div class="host">On <b id="host"></b></div>
        <div class="h">Name this oracle</div>
        <input class="in" id="label" placeholder="e.g. BTC price, warehouse stock, order status" />
        <div class="row"><button class="btn sec" id="pick">◎ Pick element</button><button class="btn sec" id="readnow" style="flex:0 0 auto">Read</button></div>
        <div class="val" id="val">— pick a value on the page —</div>
        <div class="row">
          <div style="flex:1"><label class="fl">Reading type</label>
            <select class="in" id="rt">
              <option value="number" selected>Number</option>
              <option value="price">Price</option>
              <option value="percent">Percent</option>
              <option value="stock">Stock / count</option>
              <option value="status">Status / text</option>
              <option value="text">Raw text</option>
              <option value="json">JSON</option>
            </select>
          </div>
          <div style="flex:0 0 92px"><label class="fl">Unit</label>
            <input class="in" id="unit" placeholder="$ % units" />
          </div>
        </div>
        <label class="fl">Read every</label>
        <select class="in" id="iv">
          <option value="20">20 Zeqonds</option>
          <option value="40" selected>40 Zeqonds</option>
          <option value="80">80 Zeqonds</option>
          <option value="400">400 Zeqonds (~5 min)</option>
        </select>
        <button class="btn" id="start">Start oracle → Observer</button>
        <button class="btn sec" id="stop" style="display:none">Stop oracle</button>
        <div class="out" id="out"></div>
      </div>
    </div>`;
  document.documentElement.appendChild(root);

  const $ = (id) => shadow.getElementById(id);
  $("host").textContent = location.hostname.replace(/^www\./, "");
  function sw(msg) { return new Promise((res) => { try { chrome.runtime.sendMessage(msg, (r) => res(chrome.runtime.lastError ? null : r)); } catch (_) { res(null); } }); }

  let signedIn = false;
  sw({ type: "getSession" }).then((s) => {
    signedIn = !!(s && s.token);
    $("zid").textContent = signedIn ? s.zid : "not signed in";
    if (!signedIn) $("body").innerHTML = '<div class="signin">Sign in via the ZeqVM side panel, then inject again — the oracle records into your machine.</div>';
  });

  // ── Value capture ────────────────────────────────────────────────────────
  let selector = null;
  function cssPath(el) {
    if (el.id) return "#" + CSS.escape(el.id);
    const parts = [];
    while (el && el.nodeType === 1 && parts.length < 5) {
      let p = el.tagName.toLowerCase();
      if (el.className && typeof el.className === "string") { const c = el.className.trim().split(/\s+/)[0]; if (c) p += "." + CSS.escape(c); }
      const par = el.parentElement;
      if (par) { const sibs = Array.prototype.filter.call(par.children, (n) => n.tagName === el.tagName); if (sibs.length > 1) p += ":nth-of-type(" + (sibs.indexOf(el) + 1) + ")"; }
      parts.unshift(p); el = par;
    }
    return parts.join(" > ");
  }
  function rawValue() {
    if (!selector) return (document.title || "").trim().slice(0, 200);
    try { const el = document.querySelector(selector); return el ? (el.textContent || "").trim().slice(0, 200) : "(not found)"; } catch (_) { return "(bad selector)"; }
  }
  // Coerce per reading-type so the Observer stores a clean, typed value.
  function typedValue() {
    const raw = rawValue();
    const rt = $("rt").value;
    if (rt === "text" || rt === "status") return raw;
    if (rt === "json") { try { return JSON.parse(raw); } catch (_) { return raw; } }
    // number / price / percent / stock — strip currency/commas/%, parse float
    const num = parseFloat(String(raw).replace(/[^0-9.\-]/g, ""));
    return Number.isFinite(num) ? num : raw;
  }
  function showVal() {
    const v = typedValue();
    $("val").textContent = (typeof v === "object" ? JSON.stringify(v) : String(v)) || "(empty)";
  }

  $("pick").addEventListener("click", () => {
    $("out").textContent = "Click any element on the page to watch it…"; $("out").className = "out";
    const onClick = (e) => {
      e.preventDefault(); e.stopPropagation();
      selector = cssPath(e.target);
      if (!$("label").value.trim()) $("label").value = (e.target.textContent || "").trim().slice(0, 40);
      showVal();
      $("out").textContent = "Picked: " + selector.slice(0, 60); $("out").className = "out ok";
      document.removeEventListener("click", onClick, true);
    };
    document.addEventListener("click", onClick, true);
  });
  $("readnow").addEventListener("click", showVal);
  $("rt").addEventListener("change", showVal);

  // ── Oracle lifecycle ───────────────────────────────────────────────────────
  let timer = null, contractId = null, slug = null, origin = null, count = 0;
  function meta() {
    return {
      label: $("label").value.trim() || "page oracle",
      selector: selector || "",
      host: location.hostname,
      url: location.href,
      reading_type: $("rt").value,
      unit: $("unit").value.trim(),
      interval_zeqonds: parseInt($("iv").value, 10) || 40,
    };
  }
  async function fireOnce() {
    const value = typedValue();
    $("val").textContent = (typeof value === "object" ? JSON.stringify(value) : String(value));
    const m = meta();
    const r = await sw({ type: "oracleFire", contractId, slug, label: m.label, value, url: m.url, host: m.host });
    if (r && r.success) { count++; $("out").innerHTML = '<span class="ok">▲ ' + count + ' reading(s) → Observer</span>' + (origin ? ' · <a href="' + origin + '/state/?slug=' + slug + '#oracles" target="_blank">open Observer</a>' : ""); }
    else { $("out").className = "out err"; $("out").textContent = "send failed: " + ((r && r.error) || "?"); }
  }
  $("start").addEventListener("click", async () => {
    if (!signedIn) { $("out").className = "out err"; $("out").textContent = "Sign in first."; return; }
    const btn = $("start"); btn.disabled = true; btn.textContent = "Deploying oracle…";
    const dep = await sw({ type: "oracleDeploy", oracle: meta() });
    if (!dep || !dep.success) { btn.disabled = false; btn.textContent = "Start oracle → Observer"; $("out").className = "out err"; $("out").textContent = "deploy failed: " + ((dep && dep.error) || "?"); return; }
    contractId = dep.contractId; slug = dep.slug; origin = dep.origin; count = 0;
    if (dep.reused) { $("out").className = "out ok"; $("out").textContent = "Reusing your existing oracle for this target — readings continue on the same entangled state."; }
    await fireOnce();
    const ms = (parseInt($("iv").value, 10) || 40) * TAU_S * 1000;
    timer = setInterval(fireOnce, ms);
    btn.style.display = "none"; $("stop").style.display = "";
  });
  $("stop").addEventListener("click", () => { if (timer) clearInterval(timer); timer = null; $("stop").style.display = "none"; $("start").style.display = ""; $("start").disabled = false; $("start").textContent = "Start oracle → Observer"; $("out").innerHTML += ' · <span class="ok">stopped</span>'; });
  $("x").addEventListener("click", () => { if (timer) clearInterval(timer); root.remove(); });

  // Drag.
  (() => { const bar = $("bar"); let sx, sy, ox, oy, drag = false;
    bar.addEventListener("mousedown", (e) => { drag = true; sx = e.clientX; sy = e.clientY; const r = root.getBoundingClientRect(); ox = r.left; oy = r.top; e.preventDefault(); });
    window.addEventListener("mousemove", (e) => { if (!drag) return; root.style.left = (ox + e.clientX - sx) + "px"; root.style.top = (oy + e.clientY - sy) + "px"; root.style.right = "auto"; });
    window.addEventListener("mouseup", () => { drag = false; });
  })();
})();
