/**
 * BOL Template Editor interactions (drag, resize, properties, persistence)
 * Works with /pages/bol_template_editor.php markup.
 */
(() => {
  const canvas = document.getElementById('template-canvas');
  if (!canvas) return;

  const mm2px = (mm) => mm * 96 / 25.4;
  const px2mm = (px) => px * 25.4 / 96;

  const snapToggle = document.getElementById('snapToggle');
  const snapSizeInput = document.getElementById('snapSize');

  const btnAdd = document.getElementById('addField');
  const btnDelete = document.getElementById('deleteField');
  const btnDuplicate = document.getElementById('duplicateField');
  const btnSaveLayout = document.getElementById('saveLayout');
  const btnReset = document.getElementById('resetLayout');

  const statusEl = document.getElementById('status');
  const btnAlignLeft = document.getElementById('alignLeft');
  const btnAlignTop = document.getElementById('alignTop');
  const btnAlignRight = document.getElementById('alignRight');

  function setStatus(msg) {
    if (statusEl) statusEl.textContent = msg;
  }

  const panel = {
    label: document.getElementById('fp_label'),
    code: document.getElementById('fp_code'),
    type: document.getElementById('fp_type'),
    font: document.getElementById('fp_font'),
    size: document.getElementById('fp_size'),
    color: document.getElementById('fp_color'),
    align: document.getElementById('fp_align'),
    multiline: document.getElementById('fp_multiline'),
  };

  let activeEl = null;
  let savingPropsTimer = null;

  function getSnapPx() {
    const on = snapToggle ? snapToggle.checked : false;
    if (!on) return 0;
    const mm = Math.max(0, parseFloat(snapSizeInput?.value || '0') || 0);
    return mm2px(mm);
  }

  function clamp(v, min, max) { return Math.max(min, Math.min(max, v)); }

  function snap(v, step) {
    if (!step || step <= 0) return v;
    return Math.round(v / step) * step;
  }

  function setActive(el) {
    if (activeEl) activeEl.classList.remove('active');
    activeEl = el;
    if (activeEl) activeEl.classList.add('active');

    const enabled = !!activeEl;
    if (btnDelete) btnDelete.disabled = !enabled;
    if (btnDuplicate) btnDuplicate.disabled = !enabled;

    fillPanelFromActive();
  }

  function fillPanelFromActive() {
    if (!activeEl) {
      for (const k of Object.keys(panel)) {
        const inp = panel[k];
        if (!inp) continue;
        if (inp.type === 'checkbox') inp.checked = false;
        else inp.value = '';
      }
      return;
    }
    panel.label && (panel.label.value = activeEl.dataset.label || activeEl.textContent.trim() || '');
    panel.code && (panel.code.value = activeEl.dataset.code || '');
    panel.type && (panel.type.value = activeEl.dataset.type || 'text');
    panel.font && (panel.font.value = activeEl.dataset.font || 'helvetica');
    panel.size && (panel.size.value = activeEl.dataset.size || '9');
    panel.color && (panel.color.value = activeEl.dataset.color || '#000000');
    panel.align && (panel.align.value = activeEl.dataset.align || 'L');
    panel.multiline && (panel.multiline.checked = (activeEl.dataset.multiline === '1'));
  }

  function applyPanelToActive() {
    if (!activeEl) return;

    const label = panel.label ? panel.label.value : '';
    const code = panel.code ? panel.code.value : '';
    const field_type = panel.type ? panel.type.value : 'text';
    const font_family = panel.font ? panel.font.value : 'helvetica';
    const font_size = panel.size ? panel.size.value : '9';
    const font_color = panel.color ? panel.color.value : '#000000';
    const align = panel.align ? panel.align.value : 'L';
    const is_multiline = panel.multiline ? (panel.multiline.checked ? 1 : 0) : 0;

    activeEl.dataset.label = label;
    activeEl.dataset.code = code;
    activeEl.dataset.type = field_type;
    activeEl.dataset.font = font_family;
    activeEl.dataset.size = font_size;
    activeEl.dataset.color = font_color;
    activeEl.dataset.align = align;
    activeEl.dataset.multiline = String(is_multiline);

    // preserve handle
    const handle = activeEl.querySelector('.resize-handle');
    activeEl.textContent = label || 'Field';
    if (handle) activeEl.appendChild(handle);

    activeEl.style.fontFamily = font_family;
    activeEl.style.fontSize = `${parseFloat(font_size) || 9}px`;
    activeEl.style.color = font_color;
    activeEl.style.textAlign = (align === 'R') ? 'right' : (align === 'C' ? 'center' : 'left');

    scheduleSaveProps(activeEl);
  }

  async function postJson(url, payload) {
    setStatus('Saving...');
    const r = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
      credentials: 'same-origin'
    });
    const ct = r.headers.get('content-type') || '';
    const text = await r.text();
    if (!r.ok) throw new Error(text || `HTTP ${r.status}`);
    const out = (ct.includes('application/json')) ? JSON.parse(text) : text;
    setStatus('Idle');
    return out;
  }

  function scheduleSaveProps(el) {
    if (!el) return;
    if (savingPropsTimer) window.clearTimeout(savingPropsTimer);
    savingPropsTimer = window.setTimeout(() => {
      savingPropsTimer = null;
      saveProps(el).catch(err => console.error(err));
    }, 400);
  }

  async function saveProps(el) {
    if (!el) return;
    const payload = {
      id: parseInt(el.dataset.id, 10),
      label: el.dataset.label || (el.textContent || '').trim(),
      code: el.dataset.code || '',
      field_type: el.dataset.type || 'text',
      font_family: el.dataset.font || 'helvetica',
      font_size: parseFloat(el.dataset.size || '9') || 9,
      font_color: el.dataset.color || '#000000',
      align: el.dataset.align || 'L',
      is_multiline: (el.dataset.multiline === '1') ? 1 : 0
    };
    await postJson('/smproduce/pages/save_bol_field_props.php', payload);
  }

  function getLayoutMm(el) {
    const x = parseFloat(el.style.left || '0');
    const y = parseFloat(el.style.top || '0');
    const w = parseFloat(el.style.width || '0');
    const h = parseFloat(el.style.height || '0');

    return {
      id: parseInt(el.dataset.id, 10),
      x_mm: px2mm(x),
      y_mm: px2mm(y),
      w_mm: px2mm(w),
      h_mm: px2mm(h),
    };
  }

  async function saveLayout(onlyEl = null) {
    const els = onlyEl ? [onlyEl] : Array.from(canvas.querySelectorAll('.bol-field'));
    const payload = els.map(getLayoutMm);
    await postJson('/smproduce/pages/save_bol_layout.php', payload);
  }

  function resetLayout() {
    const cw = canvas.clientWidth;
    const ch = canvas.clientHeight;
    Array.from(canvas.querySelectorAll('.bol-field')).forEach((el, idx) => {
      el.style.left = `${10 + (idx % 5) * 10}px`;
      el.style.top = `${10 + Math.floor(idx / 5) * 10}px`;
      el.style.width = `${mm2px(40)}px`;
      el.style.height = `${mm2px(8)}px`;
    });
  }

  function withinCanvas(x, y, w, h) {
    const cw = canvas.clientWidth;
    const ch = canvas.clientHeight;
    x = clamp(x, 0, Math.max(0, cw - w));
    y = clamp(y, 0, Math.max(0, ch - h));
    w = clamp(w, 10, cw);
    h = clamp(h, 10, ch);
    return { x, y, w, h };
  }

  function wireField(el) {
    el.style.touchAction = 'none';
    el.addEventListener('pointerdown', (e) => {
      if (e.button !== undefined && e.button !== 0) return;

      setActive(el);

      // ✅ CORNER-ONLY: se clicchi .resize-handle => resize, altrimenti move
      const isResizeCorner = e.target.classList.contains('resize-handle');
      const mode = isResizeCorner ? 'corner' : 'move';

      const start = {
        pointerId: e.pointerId,
        startX: e.clientX,
        startY: e.clientY,
        left: parseFloat(el.style.left || '0'),
        top: parseFloat(el.style.top || '0'),
        width: parseFloat(el.style.width || '0'),
        height: parseFloat(el.style.height || '0'),
        mode
      };

      const snapPx = getSnapPx();
      el.setPointerCapture(e.pointerId);

      const onMove = (ev) => {
        if (ev.pointerId !== start.pointerId) return;

        const dx = ev.clientX - start.startX;
        const dy = ev.clientY - start.startY;

        let x = start.left;
        let y = start.top;
        let w = start.width;
        let h = start.height;

        if (start.mode === 'move') {
          x = snap(start.left + dx, snapPx);
          y = snap(start.top + dy, snapPx);
        } else if (start.mode === 'corner') {
          w = snap(start.width + dx, snapPx);
          h = snap(start.height + dy, snapPx);
        }

        const bounded = withinCanvas(x, y, w, h);
        el.style.left = `${bounded.x}px`;
        el.style.top = `${bounded.y}px`;
        el.style.width = `${bounded.w}px`;
        el.style.height = `${bounded.h}px`;
      };

      const onStop = async () => {
        try { el.releasePointerCapture(start.pointerId); } catch {}
        el.removeEventListener('pointermove', onMove);
        el.removeEventListener('pointerup', onStop);
        el.removeEventListener('pointercancel', onStop);

        try { await saveLayout(el); } catch (err) { console.error(err); }
      };

      el.addEventListener('pointermove', onMove);
      el.addEventListener('pointerup', onStop);
      el.addEventListener('pointercancel', onStop);

      e.preventDefault();
    });
  }

  // Wire existing fields
  Array.from(canvas.querySelectorAll('.bol-field')).forEach(wireField);

  // Clicking on empty space clears selection
  canvas.addEventListener('pointerdown', (e) => {
    if (e.target === canvas || e.target.id === 'template-bg') setActive(null);
  });

  // Panel listeners
  Object.values(panel).forEach((inp) => {
    if (!inp) return;
    const evt = (inp.type === 'checkbox') ? 'change' : 'input';
    inp.addEventListener(evt, () => applyPanelToActive());
  });

  // Buttons
  btnAdd && btnAdd.addEventListener('click', async () => {
    try {
      const j = await postJson('/smproduce/pages/add_bol_field.php', {});
      if (!j || !j.ok) throw new Error(j?.error || 'Add failed');

      const el = document.createElement('div');
      // ✅ nuovo field: classe "new" (bordo leggero)
      el.className = 'bol-field bol-field-new';

      el.dataset.id = String(j.id);
      el.dataset.code = j.code || '';
      el.dataset.type = j.field_type || 'text';
      el.dataset.font = j.font_family || 'helvetica';
      el.dataset.size = String(j.font_size || 9);
      el.dataset.color = j.font_color || '#000000';
      el.dataset.align = j.align || 'L';
      el.dataset.multiline = String(j.is_multiline || 0);
      el.dataset.label = j.label || 'New Field';

      el.style.left = `${mm2px(10)}px`;
      el.style.top = `${mm2px(10)}px`;
      el.style.width = `${mm2px(40)}px`;
      el.style.height = `${mm2px(8)}px`;
      el.style.fontFamily = el.dataset.font;
      el.style.fontSize = `${parseFloat(el.dataset.size) || 9}px`;
      el.style.color = el.dataset.color;
      el.style.textAlign = 'left';
      el.textContent = el.dataset.label;

      // ✅ solo handle corner
      const hc = document.createElement('div');
      hc.className = 'resize-handle';
      el.appendChild(hc);

      canvas.appendChild(el);
      wireField(el);
      setActive(el);

      await saveLayout(el);
      await saveProps(el);
    } catch (err) {
      console.error(err);
      alert('Unable to add field: ' + err.message);
    }
  });

  btnDelete && btnDelete.addEventListener('click', async () => {
    if (!activeEl) return;
    const id = parseInt(activeEl.dataset.id, 10);
    if (!id) return;

    try {
      const j = await postJson('/smproduce/pages/delete_bol_field.php', { id });
      if (!j || !j.ok) throw new Error(j?.error || 'Delete failed');
      activeEl.remove();
      setActive(null);
    } catch (err) {
      console.error(err);
      alert('Unable to delete field: ' + err.message);
    }
  });

  btnDuplicate && btnDuplicate.addEventListener('click', async () => {
    if (!activeEl) return;
    const src = activeEl;

    try {
      const j = await postJson('/smproduce/pages/add_bol_field.php', {});
      if (!j || !j.ok) throw new Error(j?.error || 'Add failed');

      const el = document.createElement('div');
      el.className = 'bol-field';
      el.dataset.id = String(j.id);

      el.dataset.label = src.dataset.label || (src.textContent || '').trim();
      el.dataset.code = src.dataset.code || '';
      el.dataset.type = src.dataset.type || 'text';
      el.dataset.font = src.dataset.font || 'helvetica';
      el.dataset.size = src.dataset.size || '9';
      el.dataset.color = src.dataset.color || '#000000';
      el.dataset.align = src.dataset.align || 'L';
      el.dataset.multiline = src.dataset.multiline || '0';

      const left = parseFloat(src.style.left || '0') + mm2px(2);
      const top = parseFloat(src.style.top || '0') + mm2px(2);
      const width = parseFloat(src.style.width || '0');
      const height = parseFloat(src.style.height || '0');

      const bounded = withinCanvas(left, top, width, height);
      el.style.left = `${bounded.x}px`;
      el.style.top = `${bounded.y}px`;
      el.style.width = `${bounded.w}px`;
      el.style.height = `${bounded.h}px`;

      el.style.fontFamily = el.dataset.font;
      el.style.fontSize = `${parseFloat(el.dataset.size) || 9}px`;
      el.style.color = el.dataset.color;
      el.style.textAlign = (el.dataset.align === 'R') ? 'right' : (el.dataset.align === 'C' ? 'center' : 'left');

      el.textContent = el.dataset.label || 'Field';

      // ✅ solo handle corner
      const hc = document.createElement('div');
      hc.className = 'resize-handle';
      el.appendChild(hc);

      canvas.appendChild(el);
      wireField(el);
      setActive(el);

      await saveLayout(el);
      await saveProps(el);
    } catch (err) {
      console.error(err);
      alert('Unable to duplicate field: ' + err.message);
    }
  });

  btnSaveLayout && btnSaveLayout.addEventListener('click', async () => {
    try {
      await saveLayout(null);
      alert('Layout saved.');
    } catch (err) {
      console.error(err);
      alert('Unable to save layout: ' + err.message);
    }
  });

  btnReset && btnReset.addEventListener('click', async () => {
    resetLayout();
    try { await saveLayout(null); } catch (err) { console.error(err); }
  });

  // Align helpers
  function alignActive(which) {
    if (!activeEl) return;
    const cw = canvas.clientWidth;
    const w = parseFloat(activeEl.style.width || '0');
    const h = parseFloat(activeEl.style.height || '0');
    let x = parseFloat(activeEl.style.left || '0');
    let y = parseFloat(activeEl.style.top || '0');

    if (which === 'left') x = 0;
    if (which === 'top') y = 0;
    if (which === 'right') x = Math.max(0, cw - w);

    const bounded = withinCanvas(x, y, w, h);
    activeEl.style.left = `${bounded.x}px`;
    activeEl.style.top = `${bounded.y}px`;

    saveLayout(activeEl).catch(err => console.error(err));
  }

  btnAlignLeft && btnAlignLeft.addEventListener('click', () => alignActive('left'));
  btnAlignTop && btnAlignTop.addEventListener('click', () => alignActive('top'));
  btnAlignRight && btnAlignRight.addEventListener('click', () => alignActive('right'));

})();
