// Adom Pup service worker — per-tab owner badge + the snip keyboard command.
// Polls pup /health (cheap, cached port) and badges each tab whose URL matches a pup session
// with the owning thread's initials + a stable per-thread color. Settings-aware: pup's
// toolbarExtension/tbOwnerBadge prefs ride /health; OFF clears badges and stands down.
const CANDIDATE_PORTS = [64230, 8851];

async function findPort() {
  const { pupPort } = await chrome.storage.local.get('pupPort');
  const ports = pupPort ? [pupPort, ...CANDIDATE_PORTS.filter(p => p !== pupPort)] : CANDIDATE_PORTS;
  for (const port of ports) {
    try {
      const r = await fetch(`http://127.0.0.1:${port}/health`, { signal: AbortSignal.timeout(1200) });
      const j = await r.json();
      if (j && j.bridge === 'puppeteer') { chrome.storage.local.set({ pupPort: port }); return { port, health: j }; }
    } catch (e) {}
  }
  return null;
}

function threadColor(name) {
  let h = 0;
  for (let i = 0; i < (name || '').length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
  const palette = ['#f59e0b', '#38bdf8', '#39d98a', '#c084fc', '#fb7185', '#5eead4'];
  return palette[h % palette.length];
}
function initials(name) {
  const parts = String(name || '').split(/[\s-_]+/).filter(Boolean);
  return (parts.length >= 2 ? parts[0][0] + parts[1][0] : String(name || '??').slice(0, 2)).toUpperCase();
}

async function sweepBadges() {
  const found = await findPort();
  if (!found) return;
  const sessions = found.health.sessions || [];
  const tabs = await chrome.tabs.query({});
  for (const tab of tabs) {
    if (!tab.url) continue;
    const hit = sessions.find(s => s.url && (s.url === tab.url || tab.url.startsWith((s.url || '').split('?')[0])));
    try {
      if (hit && hit.owner) {
        chrome.action.setBadgeText({ tabId: tab.id, text: initials(hit.owner) });
        chrome.action.setBadgeBackgroundColor({ tabId: tab.id, color: threadColor(hit.owner) });
        chrome.action.setTitle({ tabId: tab.id, title: `Adom Pup — ${hit.owner}'s window` });
      } else {
        chrome.action.setBadgeText({ tabId: tab.id, text: '' });
      }
    } catch (e) {}
  }
}

chrome.alarms.create('pup-badges', { periodInMinutes: 0.5 });
chrome.alarms.onAlarm.addListener(a => { if (a.name === 'pup-badges') sweepBadges(); });
chrome.tabs.onActivated.addListener(() => sweepBadges());
chrome.runtime.onStartup.addListener(() => sweepBadges());
sweepBadges();

// content-script bridge: the floaty pencil's config + click routing (page cannot reach the
// loopback itself; the worker can)
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  (async () => {
    if (msg && msg.t === 'pup-floaty-cfg') {
      const found = await findPort();
      const tb = (found && found.health && found.health.toolbar) || {};
      sendResponse({ enabled: !!found && tb.enabled !== false && tb.floaty !== false });
      return;
    }
    if (msg && msg.t === 'pup-annotate') {
      const found = await findPort();
      if (!found || !sender.tab || !sender.tab.url) { sendResponse({ ok: false }); return; }
      await fetch(`http://127.0.0.1:${found.port}/command`, {
        method: 'POST',
        headers: { 'content-type': 'application/json', 'x-adom-caller-thread': 'user-toolbar', 'x-adom-caller-reason': 'floaty pencil click' },
        body: JSON.stringify({ command: 'pup_annotate', args: { _tabUrl: sender.tab.url, tool: msg.tool || 'pen', caller: { aiThread: 'user-toolbar' } } }),
      }).catch(() => {});
      sendResponse({ ok: true });
    }
  })();
  return true;
});

// v2.0.64: programmatic content-script injection. Declarative content_scripts do not fire under
// this --load-extension path (verified live: zero injection on any site while the worker, popup,
// and action all work), so the worker injects the floaty itself when a tab finishes loading.
chrome.tabs.onUpdated.addListener((tabId, info, tab) => {
  if (info.status !== 'complete' || !tab || !tab.url || !/^https?:/.test(tab.url)) return;
  chrome.scripting.executeScript({ target: { tabId }, files: ['content.js'] }).catch(() => {});
});

chrome.commands.onCommand.addListener(async (command) => {
  if (command !== 'pup-snip') return;
  const found = await findPort();
  if (!found) return;
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  if (!tab || !tab.url) return;
  // v2.0.60: resolve server-side by ANY tab URL (the 2.0.58 popup fix; the hotkey had the same
  // main-page-only matching bug — the reason snip "never worked" from the keyboard)
  await fetch(`http://127.0.0.1:${found.port}/command`, {
    method: 'POST',
    headers: { 'content-type': 'application/json', 'x-adom-caller-thread': 'user-toolbar', 'x-adom-caller-reason': 'Ctrl+Shift+A annotate hotkey' },
    body: JSON.stringify({ command: 'pup_annotate', args: { _tabUrl: tab.url, tool: 'pen', caller: { aiThread: 'user-toolbar' } } }),
  }).catch(() => {});
});