/* JustZix — onboarding / samouczek na FRONCIE (coach-marks na stronie).
 * Content-script: ładowany przez manifest.json po content.js. Niezależny od
 * onboarding.js (panel edycji). Wariant wizualny: Glow (sam pierścień, bez
 * przyciemniania strony). Wszystkie klasy mają prefiks jz-obf-.
 *
 * Stan obecny: SILNIK. Scenariusze (F1–F4) dodawane osobno — patrz
 * justzix-docs/onboarding-scenarios.md, część 3.
 *
 * API globalne: window.JZ_ONBOARD_FRONT = { open(), start(id), hasScenarios() }
 */
(function () {
  'use strict';

  var STORE_KEY = 'jzOnboarding';
  // Stan współdzielony z panelem (onboarding.js) — front używa własnych pól.
  var state = { frontCompleted: false, frontFirstRunDone: false };

  // ---- Lokalizacja i ikony ------------------------------------------------
  // i18n: lib/i18n.js jest w content_scripts przed tym plikiem (JZ_I18N global).
  function t(key) {
    try { return JZ_I18N.t(key); } catch (e) { return key; }
  }
  // Ikony z zestawu JustZix (lib/icons.js NIE jest content-scriptem — inline).
  var ICONS = {
    target: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square" stroke-linejoin="miter"><path d="M12 2L22 12L12 22L2 12Z"/><circle cx="12" cy="12" r="3" fill="currentColor" stroke="none"/></svg>',
    arrowRight: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square" stroke-linejoin="miter"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>'
  };
  function icon(name) { return ICONS[name] || ''; }

  // ---- Scenariusze --------------------------------------------------------
  // Format kroku identyczny jak w onboarding.js: { target, place, interactive, code }.
  // Tytuł/treść z i18n: onboard.<scenario.i18n>.s<N>.title / .body.
  // TODO (F1–F4): front-basics, front-windows, front-actionbars, front-console-help.
  var SCENARIOS = [];

  function scenarioById(id) {
    return SCENARIOS.filter(function (s) { return s.id === id; })[0] || null;
  }

  // ---- Stan / persystencja ------------------------------------------------
  function loadState(cb) {
    try {
      chrome.storage.local.get([STORE_KEY], function (d) {
        if (d && d[STORE_KEY] && typeof d[STORE_KEY] === 'object') {
          var s = d[STORE_KEY];
          if (typeof s.frontCompleted === 'boolean') state.frontCompleted = s.frontCompleted;
          if (typeof s.frontFirstRunDone === 'boolean') state.frontFirstRunDone = s.frontFirstRunDone;
        }
        cb && cb();
      });
    } catch (e) { cb && cb(); }
  }
  // Zapis scala pola front z istniejącym obiektem (nie nadpisuje stanu panelu).
  function saveState() {
    try {
      chrome.storage.local.get([STORE_KEY], function (d) {
        var s = (d && d[STORE_KEY] && typeof d[STORE_KEY] === 'object') ? d[STORE_KEY] : {};
        s.frontCompleted = state.frontCompleted;
        s.frontFirstRunDone = state.frontFirstRunDone;
        chrome.storage.local.set({ [STORE_KEY]: s });
      });
    } catch (e) {}
  }

  // ---- Silnik coach-marków ------------------------------------------------
  var root = null, spot = null, ring = null, bubble = null;
  var scenario = null, stepIdx = 0;
  var pendingTarget = null, waitTimer = 0, layoutRaf = 0;
  var interactiveCleanup = null;

  function onKey(e) {
    if (e.key === 'Escape') { e.preventDefault(); e.stopPropagation(); skip(); }
  }

  function cleanup() {
    if (waitTimer) { clearInterval(waitTimer); waitTimer = 0; }
    if (interactiveCleanup) { interactiveCleanup(); interactiveCleanup = null; }
    window.removeEventListener('scroll', onLayout, true);
    window.removeEventListener('resize', onLayout);
    document.removeEventListener('keydown', onKey, true);
    if (root && root.parentNode) root.parentNode.removeChild(root);
    root = spot = ring = bubble = null;
    scenario = null;
  }

  function buildRoot() {
    root = document.createElement('div');
    root.className = 'jz-obf-root';
    spot = document.createElement('div'); spot.className = 'jz-obf-spot';
    ring = document.createElement('div'); ring.className = 'jz-obf-ring';
    bubble = document.createElement('div'); bubble.className = 'jz-obf-bubble';
    root.appendChild(spot); root.appendChild(ring); root.appendChild(bubble);
    document.body.appendChild(root);
    window.addEventListener('scroll', onLayout, true);
    window.addEventListener('resize', onLayout);
    document.addEventListener('keydown', onKey, true);
  }

  function onLayout() {
    if (layoutRaf) return;
    layoutRaf = requestAnimationFrame(function () { layoutRaf = 0; position(); });
  }

  function isVisible(el) {
    if (!el) return false;
    var r = el.getBoundingClientRect();
    return r.width > 1 && r.height > 1 && el.getClientRects().length > 0;
  }

  // Czeka aż cel pojawi się i będzie widoczny; po timeoucie zwraca null
  // (krok renderuje się wyśrodkowany — patrz position()).
  function waitForTarget(sel, cb) {
    if (!sel) { cb(null); return; }
    var el = document.querySelector(sel);
    if (isVisible(el)) { cb(el); return; }
    var started = Date.now();
    waitTimer = setInterval(function () {
      var e = document.querySelector(sel);
      if (isVisible(e)) { clearInterval(waitTimer); waitTimer = 0; cb(e); }
      else if (Date.now() - started > 5200) { clearInterval(waitTimer); waitTimer = 0; cb(null); }
    }, 120);
  }

  function start(scenarioId) {
    var sc = scenarioById(scenarioId);
    if (!sc) return;
    closeLauncher();
    cleanup();
    scenario = sc;
    stepIdx = 0;
    buildRoot();
    goStep(0);
  }

  function goStep(i) {
    if (!scenario) return;
    if (i < 0) i = 0;
    if (i >= scenario.steps.length) { finish(); return; }
    stepIdx = i;
    if (waitTimer) { clearInterval(waitTimer); waitTimer = 0; }
    if (interactiveCleanup) { interactiveCleanup(); interactiveCleanup = null; }
    var step = scenario.steps[i];
    bubble.classList.remove('jz-obf-in');
    waitForTarget(step.target, function (el) {
      pendingTarget = el;
      renderStep(step, el);
    });
  }

  function renderStep(step, el) {
    var n = scenario.steps.length;
    var last = stepIdx === n - 1;
    var pct = Math.round(((stepIdx + 1) / n) * 100);
    var base = scenario.i18n + '.s' + (stepIdx + 1);
    bubble.innerHTML =
      '<div class="jz-obf-arrow"></div>' +
      '<div class="jz-obf-head">' +
        '<span class="jz-obf-badge">' + (stepIdx + 1) + '</span>' +
        '<span class="jz-obf-title"></span>' +
        '<button class="jz-obf-x" type="button" aria-label="' + t('onboard.ui.close') + '">&times;</button>' +
      '</div>' +
      '<div class="jz-obf-body"></div>' +
      (step.code ? '<div class="jz-obf-code"><pre></pre><button class="jz-obf-copy" type="button"></button></div>' : '') +
      (step.interactive && el ? '<div class="jz-obf-hint">' + icon('arrowRight') + '<span></span></div>' : '') +
      '<div class="jz-obf-foot">' +
        '<span class="jz-obf-progress">' +
          '<span class="jz-obf-bar"><span class="jz-obf-bar-fill" style="width:' + pct + '%"></span></span>' +
          '<span class="jz-obf-progress-txt">' + (stepIdx + 1) + ' / ' + n + '</span>' +
        '</span>' +
        '<span class="jz-obf-btns">' +
          (stepIdx > 0 ? '<button class="jz-obf-back" type="button"></button>' : '') +
          '<button class="jz-obf-next" type="button"></button>' +
        '</span>' +
      '</div>';
    bubble.querySelector('.jz-obf-title').textContent = t(base + '.title');
    bubble.querySelector('.jz-obf-body').innerHTML = t(base + '.body');
    bubble.querySelector('.jz-obf-x').addEventListener('click', skip);
    var nextBtn = bubble.querySelector('.jz-obf-next');
    nextBtn.textContent = last ? t('onboard.ui.finish') : t('onboard.ui.next');
    nextBtn.addEventListener('click', function () { goStep(stepIdx + 1); });
    var backBtn = bubble.querySelector('.jz-obf-back');
    if (backBtn) {
      backBtn.textContent = t('onboard.ui.back');
      backBtn.addEventListener('click', function () { goStep(stepIdx - 1); });
    }
    var hintSpan = bubble.querySelector('.jz-obf-hint span');
    if (hintSpan) hintSpan.textContent = t('onboard.ui.hint');

    if (step.code) {
      bubble.querySelector('.jz-obf-code pre').textContent = step.code;
      var copyBtn = bubble.querySelector('.jz-obf-copy');
      copyBtn.textContent = t('onboard.ui.copy');
      copyBtn.addEventListener('click', function () {
        try {
          navigator.clipboard.writeText(step.code).then(function () {
            copyBtn.textContent = t('onboard.ui.copied');
            copyBtn.classList.add('jz-obf-copied');
            setTimeout(function () {
              copyBtn.textContent = t('onboard.ui.copy');
              copyBtn.classList.remove('jz-obf-copied');
            }, 1600);
          });
        } catch (e) {}
      });
    }

    if (step.interactive && el) {
      var handler = function () { setTimeout(function () { goStep(stepIdx + 1); }, 220); };
      el.addEventListener('click', handler, { once: true });
      interactiveCleanup = function () { el.removeEventListener('click', handler); };
    }

    if (el && typeof el.scrollIntoView === 'function') {
      el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' });
      setTimeout(position, 240);
    }
    position();
    requestAnimationFrame(function () { bubble.classList.add('jz-obf-in'); });
  }

  // Pozycjonowanie spotlightu, pierścienia i dymka względem celu.
  function position() {
    if (!root || !bubble) return;
    var el = pendingTarget;
    var r = (el && isVisible(el)) ? el.getBoundingClientRect() : null;
    var bw = bubble.offsetWidth || 340, bh = bubble.offsetHeight || 160;
    var vw = window.innerWidth, vh = window.innerHeight;
    var arrow = bubble.querySelector('.jz-obf-arrow');

    if (!r) {
      spot.style.display = 'none';
      ring.style.display = 'none';
      if (arrow) arrow.style.display = 'none';
      bubble.style.left = Math.round((vw - bw) / 2) + 'px';
      bubble.style.top = Math.round((vh - bh) / 2) + 'px';
      return;
    }

    var pad = 6;
    var hx = Math.max(0, r.left - pad), hy = Math.max(0, r.top - pad);
    var hw = r.width + pad * 2, hh = r.height + pad * 2;
    spot.style.display = ring.style.display = 'block';
    spot.style.left = ring.style.left = hx + 'px';
    spot.style.top = ring.style.top = hy + 'px';
    spot.style.width = ring.style.width = hw + 'px';
    spot.style.height = ring.style.height = hh + 'px';

    var gap = 18;
    var space = { bottom: vh - r.bottom, top: r.top, right: vw - r.right, left: r.left };
    var pl = step_().place || 'bottom';
    if (pl === 'center' || pl === 'auto') pl = 'bottom';
    var need = (pl === 'top' || pl === 'bottom') ? bh + gap : bw + gap;
    if (space[pl] < need) {
      pl = Object.keys(space).sort(function (a, b) { return space[b] - space[a]; })[0];
    }

    var left, top;
    if (pl === 'bottom') { top = r.bottom + gap; left = r.left + r.width / 2 - bw / 2; }
    else if (pl === 'top') { top = r.top - gap - bh; left = r.left + r.width / 2 - bw / 2; }
    else if (pl === 'right') { left = r.right + gap; top = r.top + r.height / 2 - bh / 2; }
    else { left = r.left - gap - bw; top = r.top + r.height / 2 - bh / 2; }
    left = Math.max(12, Math.min(left, vw - bw - 12));
    top = Math.max(12, Math.min(top, vh - bh - 12));
    bubble.style.left = Math.round(left) + 'px';
    bubble.style.top = Math.round(top) + 'px';

    if (arrow) {
      arrow.style.display = 'block';
      var ax, ay;
      if (pl === 'bottom') { ay = -7; ax = r.left + r.width / 2 - left - 7; }
      else if (pl === 'top') { ay = bh - 7; ax = r.left + r.width / 2 - left - 7; }
      else if (pl === 'right') { ax = -7; ay = r.top + r.height / 2 - top - 7; }
      else { ax = bw - 7; ay = r.top + r.height / 2 - top - 7; }
      arrow.style.left = Math.max(10, Math.min(ax, bw - 24)) + 'px';
      arrow.style.top = Math.max(10, Math.min(ay, bh - 24)) + 'px';
    }
  }
  function step_() { return (scenario && scenario.steps[stepIdx]) || {}; }

  function finish() {
    state.frontCompleted = true;
    saveState();
    cleanup();
  }
  function skip() { cleanup(); }

  // ---- Launcher (centrum samouczków frontu) -------------------------------
  var launcher = null;

  function onLauncherKey(e) {
    if (e.key === 'Escape') { e.preventDefault(); e.stopPropagation(); closeLauncher(); }
  }

  function openLauncher(firstRun) {
    if (launcher) return;
    launcher = document.createElement('div');
    launcher.className = 'jz-obf-launcher';
    var body;
    if (SCENARIOS.length) {
      body =
        '<div class="jz-obf-sect-t">' + t('onboard.lr.scenarios') + '</div>' +
        SCENARIOS.map(function (s) {
          return '<div class="jz-obf-scen">' +
            '<div class="jz-obf-scen-ico">' + icon('target') + '</div>' +
            '<div class="jz-obf-scen-txt">' +
              '<div class="jz-obf-scen-name">' + t(s.i18n + '.name') + '</div>' +
              '<div class="jz-obf-scen-desc">' + t(s.i18n + '.desc') + '</div>' +
              '<div class="jz-obf-scen-meta">' + t(s.i18n + '.meta') + '</div>' +
            '</div>' +
            '<button type="button" data-scen="' + s.id + '">' + t('onboard.lr.start') + '</button>' +
          '</div>';
        }).join('');
    } else {
      body = '<div class="jz-obf-empty">' + t('onboard.front.empty') + '</div>';
    }
    launcher.innerHTML =
      '<div class="jz-obf-card">' +
        '<h2>' + (firstRun ? t('onboard.front.titleFirst') : t('onboard.front.title')) + '</h2>' +
        '<p class="jz-obf-lead">' + (firstRun ? t('onboard.front.leadFirst') : t('onboard.front.lead')) + '</p>' +
        body +
        '<div class="jz-obf-launcher-foot">' +
          '<button class="jz-obf-skip" type="button">' + t('onboard.lr.later') + '</button>' +
          '<label><input type="checkbox" class="jz-obf-noauto"' + (state.frontFirstRunDone ? ' checked' : '') + '> ' + t('onboard.lr.noAuto') + '</label>' +
        '</div>' +
      '</div>';
    document.body.appendChild(launcher);
    document.addEventListener('keydown', onLauncherKey, true);

    launcher.addEventListener('click', function (e) {
      if (e.target === launcher) closeLauncher();
    });
    Array.prototype.forEach.call(launcher.querySelectorAll('[data-scen]'), function (b) {
      b.addEventListener('click', function () { start(b.getAttribute('data-scen')); });
    });
    launcher.querySelector('.jz-obf-skip').addEventListener('click', closeLauncher);
    launcher.querySelector('.jz-obf-noauto').addEventListener('change', function (e) {
      state.frontFirstRunDone = e.target.checked;
      saveState();
    });
  }

  function closeLauncher() {
    document.removeEventListener('keydown', onLauncherKey, true);
    if (launcher && launcher.parentNode) launcher.parentNode.removeChild(launcher);
    launcher = null;
  }

  // ---- Inicjalizacja ------------------------------------------------------
  function init() {
    loadState(function () {
      if (state.frontFirstRunDone || !SCENARIOS.length) return;
      // Pierwsze uruchomienie na froncie — launcher pokaże się raz.
      state.frontFirstRunDone = true;
      saveState();
      setTimeout(function () { openLauncher(true); }, 1200);
    });
  }

  // API dla content.js (wyzwalacze: panel front, popup Ctrl+Shift+H).
  window.JZ_ONBOARD_FRONT = {
    open: function () { openLauncher(false); },
    start: start,
    hasScenarios: function () { return SCENARIOS.length > 0; }
  };

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();
