// =============================================================================
// XDock Plus → MyTruck — Background Service Worker (MV3) — v2.5
// =============================================================================
// Wakes up every 30 seconds (chrome.alarms). As long as the bureau user has AT
// LEAST ONE tab open on *.xdock.de (any page — login, listing, anywhere on the
// domain), the SW silently fetches the "En cours" HTML using that tab's session
// cookies, parses it, and POSTs the truck list to MyTruck.
//
// v2.5 — NEW : extracts BOTH the primary cariste (`Mitarbeiter`) AND the
// co-pilot (`CoPilot`) from each row, and emits 2 separate truck entries when
// a co-pilot is present (one keyed on each cariste name). This way both
// caristes on the same truck see the truck auto-fill in MyTruck.
//
// → No need to keep the "En cours" tab itself open or pinned.
// → No need for the bureau person to interact at all.
// =============================================================================

const CONFIG = {
  MYTRUCK_API: "https://www.gp-eff.fr/api/gp/xdock/current-task/upsert-bulk",
  API_KEY:     "Nlgw0hp4uIJJMSa06Yc4ZQI9-WoToTKf",
  // Relative path of the "En cours" page on whichever xdock.de subdomain the user uses.
  ENCOURS_PATH: "/Taskmanagement/TaskmanagementInArbeit?sort=TourIdASC",
  PERIOD_MIN:  0.5,    // 30 seconds
  ALARM_NAME:  "xdock-plus-sync",
};

chrome.runtime.onInstalled.addListener(() => {
  chrome.alarms.create(CONFIG.ALARM_NAME, { periodInMinutes: CONFIG.PERIOD_MIN });
  console.log("[XDock+] Installed — alarm every", CONFIG.PERIOD_MIN * 60, "s");
});

chrome.runtime.onStartup.addListener(() => {
  chrome.alarms.create(CONFIG.ALARM_NAME, { periodInMinutes: CONFIG.PERIOD_MIN });
});

chrome.alarms.onAlarm.addListener(async (alarm) => {
  if (alarm.name !== CONFIG.ALARM_NAME) return;
  try { await syncOnce(); } catch (e) { console.warn("[XDock+] tick:", e); }
});

// Manual trigger from popup
chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
  if (msg?.type === "XDOCK_SYNC_NOW") {
    syncOnce()
      .then((r) => sendResponse({ ok: true, ...r }))
      .catch((e) => sendResponse({ ok: false, error: String(e) }));
    return true;
  }
});

// -----------------------------------------------------------------------------
// Core sync logic
// -----------------------------------------------------------------------------
async function syncOnce() {
  // Look for ANY tab on the XDock+ domain (login page, any module, whatever).
  // We only need a tab that has live session cookies — the URL doesn't matter.
  const tabs = await chrome.tabs.query({ url: "*://*.xdock.de/*" });

  if (tabs.length === 0) {
    await persistSync({ count: 0, reason: "no-tab" });
    return { trucks: 0, reason: "no-tab" };
  }

  // Pick the first usable tab (prefer non-error pages)
  const tab = tabs.find((t) => /^https?:/i.test(t.url || "")) || tabs[0];

  // Inject a function into the tab that does a fetch + DOMParser of the
  // "En cours" page. Runs in MAIN world so Bootstrap tooltips (data-original-title)
  // are accessible if XDock+ ever decides to render them.
  let scraped;
  try {
    const [{ result, error }] = await chrome.scripting.executeScript({
      target: { tabId: tab.id },
      world: "MAIN",
      args: [CONFIG.ENCOURS_PATH],
      func: fetchAndScrape, // see below — sent as source to the page
    });
    if (error) throw error;
    scraped = result || [];
  } catch (e) {
    console.warn("[XDock+] inject/scrape failed:", e);
    await persistSync({ count: 0, error: String(e) });
    return { trucks: 0, error: String(e) };
  }

  console.log(`[XDock+] Scraped ${scraped.length} truck(s) via tab ${tab.id}`);

  // Push to MyTruck (always — even an empty list, so the server can age out)
  const resp = await fetch(CONFIG.MYTRUCK_API, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-XDockPlus-Key": CONFIG.API_KEY,
    },
    body: JSON.stringify({ trucks: scraped }),
  });

  if (!resp.ok) {
    const txt = await resp.text();
    const errMsg = `MyTruck API ${resp.status}: ${txt.slice(0, 200)}`;
    await persistSync({ count: scraped.length, error: errMsg });
    throw new Error(errMsg);
  }

  const data = await resp.json();
  await persistSync({ count: scraped.length, upserted: data.upserted || 0 });
  return { trucks: scraped.length, ...data };
}

async function persistSync(payload) {
  await chrome.storage.local.set({
    lastSync: { ts: Date.now(), ...payload },
  });
}

// =============================================================================
// fetchAndScrape — INJECTED into the xdock.de tab.
// Runs in the page context, so its fetch() inherits the user's session cookies.
// =============================================================================
function fetchAndScrape(enCoursPath) {
  // -- Build absolute URL on the SAME origin as the tab --
  const url = new URL(enCoursPath, location.origin).toString();

  return fetch(url, {
    method: "GET",
    credentials: "include",
    headers: { "X-Requested-With": "XMLHttpRequest" },
    redirect: "follow",
  })
    .then((r) => {
      if (!r.ok) throw new Error("HTTP " + r.status);
      return r.text();
    })
    .then((html) => {
      // If we got the login page back instead of the table, bail out
      if (/<form[^>]+action="?\/?[Ll]ogin/i.test(html)) {
        console.warn("[XDock+] session expired (login page returned)");
        return [];
      }

      const doc = new DOMParser().parseFromString(html, "text/html");

      const txt = (el) => (el?.textContent || "").trim().replace(/\s+/g, " ");

      const detectTourType = (tr) => {
        const a = tr.querySelector("a.btn-weTour, a.btn-waTour, a[href*='Tour']");
        const href = a?.getAttribute("href") || "";
        if (/Wareneingang/i.test(href)) return "EM";
        if (/Warenausgang/i.test(href)) return "SM";
        const id = tr.id || "";
        if (id.startsWith("WE_")) return "EM";
        if (id.startsWith("WA_")) return "SM";
        return "";
      };

      const parseTooltip = (html2) => {
        const out = { tracteur: "", remorque: "" };
        if (!html2) return out;
        const tractM = html2.match(/V[ée]hicule\s+tracteur\s*:?<\/strong>\s*([^<]+)</i);
        if (tractM) out.tracteur = tractM[1].trim();
        const remM = html2.match(/Rf\.?\s*v[ée]hicule\s*:?<\/strong>\s*([^<]+)</i);
        if (remM) out.remorque = remM[1].trim();
        return out;
      };

      const trucks = [];
      // Some XDock+ skins use <tr id="WE_xxx"> / <tr id="WA_xxx">, others just
      // <tr data-sort="123"> with a Mitarbeiter selectbox. We support both.
      const rows = doc.querySelectorAll(
        'tr[id^="WE_"], tr[id^="WA_"], tr[data-sort]'
      );
      const cleanName = (n) => {
        const s = (n || "").trim();
        if (!s || s === "-") return "";
        return s;
      };
      rows.forEach((tr) => {
        const tds = tr.querySelectorAll(":scope > td");
        if (tds.length < 4) return;
        const tourLink = tds[0].querySelector("a");
        const tour_number = txt(tourLink) || txt(tds[0]);
        if (!tour_number) return;

        // --- Primary cariste (Mitarbeiter) ---
        const mitSel = tr.querySelector(
          'select.updateMitarbeiterSelectbox, select[id^="mitarbeiterId_"]'
        );
        const primaryName = mitSel && mitSel.selectedIndex >= 0
          ? cleanName(mitSel.options[mitSel.selectedIndex]?.text)
          : "";

        // --- Co-pilot (CoPilot) ---
        const coSel = tr.querySelector(
          'select.updateCoPilotSelectbox, select[id^="coPilotId_"]'
        );
        const coName = coSel && coSel.selectedIndex >= 0
          ? cleanName(coSel.options[coSel.selectedIndex]?.text)
          : "";

        // Truck identity (tractor + trailer) lives in the info tooltip
        const infoIcon = tr.querySelector("i.fa-info-square, [data-original-title]");
        const tooltipHtml = infoIcon?.getAttribute("data-original-title") || "";
        const { tracteur, remorque } = parseTooltip(tooltipHtml);
        const tour_type = detectTourType(tr);

        // Emit one entry per assigned cariste (primary + co-pilot). If neither
        // is assigned, we skip — there's no driver yet.
        if (primaryName) {
          trucks.push({
            xdock_name:  primaryName,
            tour_number,
            tour_type,
            tracteur,
            remorque,
          });
        }
        if (coName && coName !== primaryName) {
          trucks.push({
            xdock_name:  coName,
            tour_number,
            tour_type,
            tracteur,
            remorque,
          });
        }
      });
      return trucks;
    })
    .catch((err) => {
      console.warn("[XDock+] fetchAndScrape error:", err);
      return [];
    });
}

console.log("[XDock+] Background SW v2.5 ready");
