// El Eje — extension-side data collection (OPT-IN, OFF by default).
//
// Records confirmed detections as "contributions" that feed the offline majority-vote
// pipeline (EjePlayerCodes/collect/). A contribution says "the audio on domain X was
// recording Y" — corroboration that strengthens labels across many users. We store
// ONLY: the matched song id + its (already-public) label + the page's DOMAIN (never the
// full URL, never audio, never browsing history) + an anonymous client id.
//
// STANDALONE / NOT WIRED INTO THE UI YET — review first. To enable later, call
// `collect.record(...)` from a 👍 confirm action in panel.js / content.js. Pure helpers
// (domainOf/buildContribution) are exported for testing without chrome.*.

const ENABLED_KEY = "collectEnabled";   // chrome.storage.local; default false
const QUEUE_KEY = "eleje_contributions";
const CLIENT_KEY = "eleje_client";
const MAX_QUEUE = 5000;

export function domainOf(url) {
  try { return new URL(url).hostname.replace(/^www\./, ""); } catch { return ""; }
}

// Shape a contribution compatible with EjePlayerCodes/collect (store.py schema).
export function buildContribution({ songId = null, label = null, url = "", confirmed = false, client = "anon", ts = "" }) {
  return {
    label: label || null,                 // {title,orchestra,singer,year,genre} or null (pure corroboration)
    source: "extension:" + (client || "anon"),
    matched_song_id: songId,
    domain: domainOf(url),                 // domain only — not the full URL
    confirmed: !!confirmed,                // true = user 👍'd the match
    ts,
  };
}

const hasStorage = () => typeof chrome !== "undefined" && chrome.storage && chrome.storage.local;

async function get(key, dflt) {
  if (!hasStorage()) return dflt;
  const o = await chrome.storage.local.get(key);
  return key in o ? o[key] : dflt;
}

export async function isEnabled() { return (await get(ENABLED_KEY, false)) === true; }
export async function setEnabled(on) { if (hasStorage()) await chrome.storage.local.set({ [ENABLED_KEY]: !!on }); }

async function clientId() {
  let id = await get(CLIENT_KEY, "");
  if (!id) {                              // random, anonymous, per-install
    id = "c" + Math.random().toString(36).slice(2, 10);
    if (hasStorage()) await chrome.storage.local.set({ [CLIENT_KEY]: id });
  }
  return id;
}

// Record a detection. No-op unless the user opted in.
export async function record({ songId = null, label = null, url = "", confirmed = false }) {
  if (!hasStorage() || !(await isEnabled())) return false;
  const c = buildContribution({ songId, label, url, confirmed, client: await clientId(), ts: new Date().toISOString() });
  const q = await get(QUEUE_KEY, []);
  // dedupe: same song + domain already queued -> keep one
  if (!q.some(x => x.matched_song_id === c.matched_song_id && x.domain === c.domain)) {
    q.push(c);
    if (q.length > MAX_QUEUE) q.splice(0, q.length - MAX_QUEUE);
    await chrome.storage.local.set({ [QUEUE_KEY]: q });
  }
  return true;
}

export async function count() { return (await get(QUEUE_KEY, [])).length; }
export async function clear() { if (hasStorage()) await chrome.storage.local.set({ [QUEUE_KEY]: [] }); }

// Export the queue as a JSONL string the offline `aggregate.py` can pool directly.
export async function exportJSONL() {
  const q = await get(QUEUE_KEY, []);
  return q.map(r => JSON.stringify(r)).join("\n");
}
