/* 可视化页面编辑器（可复用）：三栏布局（图标栏 | 编辑画布 | 标签页右栏）
 * 右栏：预览（只读实时模拟）/ 属性 / 素材（可删除）
 * 支持元素类型：text 文字, image 图片, button 链接按钮, buy 产品购买, price 产品价格, specs 产品规格
 * 对齐：左/中/右 + 竖（文字=竖排 writing-mode，图片=垂直居中）
 * 依赖全局（由后台 partial 注入）：
 *   __PB_INIT__   初始布局数组
 *   __PB_MODULE__ page|product|news|case|category
 *   __PB_MEDIA__  素材列表接口
 *   __PB_UPLOAD__ 上传接口
 *   __PB_DELETE__ 删除接口前缀（拼接文件名）
 *   __PB_CSRF__   CSRF 令牌
 */
(function () {
  'use strict';
  var STAGE_W = 720;
  var stage = document.getElementById('pbStage');
  if (!stage) return;
  var MODULE = (window.__PB_MODULE__ || 'page');

  var elements = Array.isArray(window.__PB_INIT__) ? window.__PB_INIT__.slice() : [];
  var selectedId = null;
  var zCounter = elements.reduce(function (m, e) { return Math.max(m, e.z || 0); }, 0);

  function uid() { return 'el_' + Date.now().toString(36) + Math.floor(Math.random() * 1e4).toString(36); }
  function nextZ() { return ++zCounter; }
  function findEl(id) { for (var i = 0; i < elements.length; i++) if (elements[i].id === id) return elements[i]; return null; }
  function nodeOf(id) { return stage.querySelector('[data-id="' + id + '"]'); }
  function ptOf(ev) { return ev.touches && ev.touches[0] ? ev.touches[0] : ev; }
  function on(id, evt, fn) { var el = document.getElementById(id); if (el) el.addEventListener(evt, fn); }

  /* ---------- 对齐样式（文字：text-align + 竖排；图片：flex 水平 + 垂直居中） ---------- */
  function styleAlign(el, node) {
    node.style.textAlign = '';
    node.style.writingMode = '';
    node.style.display = '';
    node.style.flexDirection = '';
    node.style.alignItems = '';
    node.style.justifyContent = '';
    if (el.type === 'image') {
      node.style.display = 'flex';
      node.style.flexDirection = 'column';
      node.style.alignItems = (el.align === 'center') ? 'center' : (el.align === 'right') ? 'flex-end' : 'flex-start';
      node.style.justifyContent = el.v ? 'center' : 'flex-start';
    } else if (el.type === 'text') {
      node.style.textAlign = el.align || 'left';
      if (el.v) node.style.writingMode = 'vertical-rl';
    }
  }

  /* ---------- 通用指针拖拽（鼠标 + 触摸） ---------- */
  function onPointer(ev, handlers) {
    ev.preventDefault();
    var move = function (e) { if (handlers.move) handlers.move(ptOf(e)); };
    var up = function () {
      document.removeEventListener('mousemove', move);
      document.removeEventListener('mouseup', up);
      document.removeEventListener('touchmove', move);
      document.removeEventListener('touchend', up);
      if (handlers.end) handlers.end();
    };
    document.addEventListener('mousemove', move);
    document.addEventListener('mouseup', up);
    document.addEventListener('touchmove', move, { passive: false });
    document.addEventListener('touchend', up);
    if (handlers.start) handlers.start(ptOf(ev));
  }

  /* ---------- 构建元素内部内容 ---------- */
  function buildInner(el) {
    if (el.type === 'image') {
      var im = document.createElement('img');
      im.className = 'pb-img'; im.src = el.src || ''; im.alt = ''; im.draggable = false;
      im.addEventListener('load', updateStageSize);
      return im;
    }
    if (el.type === 'button' || el.type === 'buy') {
      var a = document.createElement('a');
      a.className = 'pb-static pb-btn-prev' + (el.type === 'buy' ? ' pb-buy' : '');
      a.textContent = el.type === 'buy' ? '立即购买' : (el.text || '按钮');
      if (el.type === 'button') {
        if (el.bg) a.style.background = el.bg;
        if (el.tc) a.style.color = el.tc;
        a.style.fontSize = (el.size === 'lg' ? '18px' : el.size === 'sm' ? '13px' : '15px');
      }
      return a;
    }
    if (el.type === 'price') {
      var d = document.createElement('div');
      d.className = 'pb-static pb-price-prev';
      d.textContent = '¥ — 起/套';
      if (el.color) d.style.color = el.color;
      return d;
    }
    if (el.type === 'specs') {
      var t = document.createElement('div');
      t.className = 'pb-static pb-specs-prev';
      t.innerHTML = '<div class="sp-row"><span>参数 1</span><span>值 1</span></div><div class="sp-row"><span>参数 2</span><span>值 2</span></div>';
      return t;
    }
    var tx = document.createElement('div');
    tx.className = 'pb-text';
    tx.textContent = el.text != null ? el.text : '';
    tx.style.fontSize = (el.fontSize || 18) + 'px';
    tx.style.color = el.color || '#0f172a';
    tx.style.fontWeight = el.bold ? '700' : '400';
    tx.style.textAlign = el.align || 'left';
    tx.style.lineHeight = '1.4';
    return tx;
  }

  /* ---------- 渲染单个元素 ---------- */
  function renderEl(el) {
    var wrap = document.createElement('div');
    wrap.className = 'pb-el';
    wrap.setAttribute('data-id', el.id);
    wrap.style.left = (el.x || 0) + 'px';
    wrap.style.top = (el.y || 0) + 'px';
    wrap.style.width = (el.w || 200) + 'px';
    wrap.style.zIndex = el.z || 1;
    wrap.appendChild(buildInner(el));
    styleAlign(el, wrap);

    var h = document.createElement('span');
    h.className = 'pb-handle';
    h.addEventListener('mousedown', function (e) { startResize(e, el); });
    h.addEventListener('touchstart', function (e) { startResize(e, el); }, { passive: false });
    wrap.appendChild(h);

    wrap.addEventListener('mousedown', function (e) { startDrag(e, el); });
    wrap.addEventListener('touchstart', function (e) { startDrag(e, el); }, { passive: false });
    wrap.addEventListener('click', function (e) { e.stopPropagation(); selectEl(el.id); });
    if (el.type === 'text') {
      wrap.addEventListener('dblclick', function (e) { e.stopPropagation(); startEdit(el, wrap.firstChild); });
    }
    return wrap;
  }

  function renderAll() {
    stage.innerHTML = '';
    elements.forEach(function (el) { stage.appendChild(renderEl(el)); });
    if (selectedId && nodeOf(selectedId)) nodeOf(selectedId).classList.add('sel');
    updateStageSize();
    renderPreview();
  }

  /* 画布高度自适应：容纳所有元素底部 */
  function updateStageSize() {
    var maxB = 480;
    elements.forEach(function (el) {
      var n = nodeOf(el.id);
      if (!n) return;
      var b = (el.y || 0) + n.offsetHeight;
      if (b > maxB) maxB = b;
    });
    stage.style.minHeight = maxB + 'px';
  }

  function applyEl(el) {
    var n = nodeOf(el.id);
    if (!n) return;
    n.style.width = (el.w || 200) + 'px';
    styleAlign(el, n);
    var inner = n.firstChild;
    if (el.type === 'image') {
      inner.src = el.src || '';
    } else if (el.type === 'text') {
      inner.textContent = el.text != null ? el.text : '';
      inner.style.fontSize = (el.fontSize || 18) + 'px';
      inner.style.color = el.color || '#0f172a';
      inner.style.fontWeight = el.bold ? '700' : '400';
      inner.style.textAlign = el.align || 'left';
      inner.style.writingMode = el.v ? 'vertical-rl' : '';
    } else if (el.type === 'button') {
      inner.textContent = el.text || '按钮';
      if (el.bg) inner.style.background = el.bg;
      if (el.tc) inner.style.color = el.tc;
      inner.style.fontSize = (el.size === 'lg' ? '18px' : el.size === 'sm' ? '13px' : '15px');
    } else if (el.type === 'price') {
      if (el.color) inner.style.color = el.color;
    }
    updateStageSize();
    renderPreview();
  }

  /* ---------- 拖拽移动 ---------- */
  function startDrag(e, el) {
    if (e.target && e.target.classList.contains('pb-handle')) return;
    e.stopPropagation();
    selectEl(el.id);
    var p = ptOf(e);
    var sx = p.clientX, sy = p.clientY, ox = el.x || 0, oy = el.y || 0;
    onPointer(e, {
      move: function (p2) {
        el.x = Math.max(0, ox + (p2.clientX - sx));
        el.y = Math.max(0, oy + (p2.clientY - sy));
        var n = nodeOf(el.id);
        if (n) { n.style.left = el.x + 'px'; n.style.top = el.y + 'px'; }
      }
    });
  }

  /* ---------- 缩放（右下角） ---------- */
  function startResize(e, el) {
    e.stopPropagation(); e.preventDefault();
    selectEl(el.id);
    var p = ptOf(e);
    var sx = p.clientX, sw = el.w || 200;
    onPointer(e, {
      move: function (p2) {
        el.w = Math.max(40, sw + (p2.clientX - sx));
        var n = nodeOf(el.id);
        if (n) n.style.width = el.w + 'px';
      }
    });
  }

  /* ---------- 双击编辑文字 ---------- */
  function startEdit(el, node) {
    node.setAttribute('contenteditable', 'true');
    node.focus();
    try { document.getSelection().selectAllChildren(node); } catch (x) {}
    function done() {
      node.removeAttribute('contenteditable');
      el.text = node.textContent;
      node.removeEventListener('blur', done);
      if (selectedId === el.id) { syncProps(); renderPreview(); }
    }
    node.addEventListener('blur', done);
  }

  /* ---------- 选中 / 属性面板 ---------- */
  function selectEl(id) {
    selectedId = id;
    Array.prototype.forEach.call(stage.querySelectorAll('.pb-el'), function (n) {
      n.classList.toggle('sel', n.getAttribute('data-id') === id);
    });
    renderProps(findEl(id));
    if (id) switchTab('props');
  }

  function alignGroup(el, types) {
    var html = '<label>对齐</label><div class="pb-align">';
    html += '<button type="button" class="pb-ab" data-a="left">左</button>';
    html += '<button type="button" class="pb-ab" data-a="center">中</button>';
    html += '<button type="button" class="pb-ab" data-a="right">右</button>';
    html += '<button type="button" class="pb-ab" data-a="v">竖</button>';
    html += '</div>';
    return html;
  }
  function wireAlign(el) {
    document.querySelectorAll('#pbPropsBody .pb-ab').forEach(function (b) {
      var a = b.getAttribute('data-a');
      var on = (a === 'v') ? !!el.v : ((el.align || 'left') === a);
      b.classList.toggle('active', on);
      b.onclick = function () {
        if (a === 'v') el.v = !el.v; else el.align = a;
        wireAlign(el); applyEl(el); renderPreview();
      };
    });
  }

  function renderProps(el) {
    var body = document.getElementById('pbPropsBody');
    if (!el) { body.className = 'pb-empty'; body.textContent = '在画布中选择一个元素以编辑属性'; return; }
    body.className = '';
    if (el.type === 'text') {
      body.innerHTML =
        '<label>文字内容</label><textarea id="pp_text" rows="3"></textarea>' +
        '<label>字号 (px)</label><input type="number" id="pp_size" min="10" max="160">' +
        '<label>颜色</label><input type="color" id="pp_color">' +
        '<label style="display:flex;align-items:center;gap:6px"><input type="checkbox" id="pp_bold"> 加粗</label>' +
        alignGroup(el) +
        '<button class="pb-del" id="pp_del" type="button">删除该元素</button>';
      document.getElementById('pp_text').value = el.text != null ? el.text : '';
      document.getElementById('pp_size').value = el.fontSize || 18;
      document.getElementById('pp_color').value = el.color || '#0f172a';
      document.getElementById('pp_bold').checked = !!el.bold;
      bind('pp_text', 'input', function (v) { el.text = v; applyEl(el); });
      bind('pp_size', 'input', function (v) { el.fontSize = parseInt(v, 10) || 18; applyEl(el); });
      bind('pp_color', 'input', function (v) { el.color = v; applyEl(el); });
      bind('pp_bold', 'change', function (v) { el.bold = !!v; applyEl(el); });
      wireAlign(el);
    } else if (el.type === 'image') {
      body.innerHTML =
        '<label>图片宽度 (px)</label><input type="number" id="pp_w" min="40" max="3000">' +
        alignGroup(el) +
        '<label>替换图片（点击素材）</label><div class="pb-lib" id="pp_lib"></div>' +
        '<button class="pb-del" id="pp_del" type="button">删除该元素</button>';
      document.getElementById('pp_w').value = el.w || 200;
      bind('pp_w', 'input', function (v) { el.w = Math.max(40, parseInt(v, 10) || 200); applyEl(el); });
      fillLib(document.getElementById('pp_lib'), function (url) { el.src = url; applyEl(el); });
      wireAlign(el);
    } else if (el.type === 'button') {
      body.innerHTML =
        '<label>按钮文字</label><input type="text" id="pp_text">' +
        '<label>链接地址</label><input type="text" id="pp_href" placeholder="如 /contact 或 https://...">' +
        '<label>背景色</label><input type="color" id="pp_bg">' +
        '<label>文字颜色</label><input type="color" id="pp_tc">' +
        '<label>尺寸</label><select id="pp_size"><option value="sm">小</option><option value="md">中</option><option value="lg">大</option></select>' +
        '<button class="pb-del" id="pp_del" type="button">删除该元素</button>';
      document.getElementById('pp_text').value = el.text || '按钮';
      document.getElementById('pp_href').value = el.href || '';
      document.getElementById('pp_bg').value = el.bg || '#0ea5e9';
      document.getElementById('pp_tc').value = el.tc || '#ffffff';
      document.getElementById('pp_size').value = el.size || 'md';
      bind('pp_text', 'input', function (v) { el.text = v; applyEl(el); });
      bind('pp_href', 'input', function (v) { el.href = v; });
      bind('pp_bg', 'input', function (v) { el.bg = v; applyEl(el); });
      bind('pp_tc', 'input', function (v) { el.tc = v; applyEl(el); });
      bind('pp_size', 'change', function (v) { el.size = v; applyEl(el); });
    } else if (el.type === 'price') {
      body.innerHTML =
        '<p class="pb-empty" style="margin-bottom:10px">自动显示本产品「价格」，无需填写。</p>' +
        '<label>价格文字颜色</label><input type="color" id="pp_color">' +
        '<button class="pb-del" id="pp_del" type="button">删除该元素</button>';
      document.getElementById('pp_color').value = el.color || '#0f172a';
      bind('pp_color', 'input', function (v) { el.color = v; applyEl(el); });
    } else if (el.type === 'buy') {
      body.innerHTML = '<p class="pb-empty">自动链接到本产品的「立即购买」下单页。</p><button class="pb-del" id="pp_del" type="button">删除该元素</button>';
    } else if (el.type === 'specs') {
      body.innerHTML = '<p class="pb-empty">自动显示本产品的「规格参数」。</p><button class="pb-del" id="pp_del" type="button">删除该元素</button>';
    }
    var del = document.getElementById('pp_del');
    if (del) del.addEventListener('click', function () { removeEl(el.id); });
  }

  function bind(id, evt, fn) {
    var el = document.getElementById(id);
    if (!el) return;
    el.addEventListener(evt, function () { fn(el.value !== undefined ? el.value : el.checked); });
  }
  function syncProps() { var el = findEl(selectedId); if (el) renderProps(el); }

  function removeEl(id) {
    elements = elements.filter(function (e) { return e.id !== id; });
    if (selectedId === id) selectedId = null;
    renderAll();
    switchTab('preview');
    if (!selectedId) renderProps(null);
  }

  /* ---------- 标签页切换 ---------- */
  function switchTab(name) {
    document.querySelectorAll('.pb-tab').forEach(function (t) {
      t.classList.toggle('active', t.getAttribute('data-tab') === name);
    });
    var panes = { preview: 'panePreview', props: 'paneProps', material: 'paneMaterial' };
    Object.keys(panes).forEach(function (k) {
      document.getElementById(panes[k]).classList.toggle('hidden', k !== name);
    });
    if (name === 'preview') fitPreview();
  }
  document.querySelectorAll('.pb-tab').forEach(function (t) {
    t.addEventListener('click', function () { switchTab(t.getAttribute('data-tab')); });
  });

  /* ---------- 实时预览（克隆只读 + 自适应缩放） ---------- */
  function renderPreview() {
    var pv = document.getElementById('pbPreview');
    if (!pv) return;
    pv.innerHTML = stage.innerHTML;
    pv.querySelectorAll('.pb-handle').forEach(function (h) { h.remove(); });
    pv.querySelectorAll('.pb-el').forEach(function (n) { n.classList.remove('sel'); n.style.outline = ''; });
    pv.querySelectorAll('[contenteditable]').forEach(function (n) { n.removeAttribute('contenteditable'); });
    fitPreview();
  }
  function fitPreview() {
    var wrap = document.getElementById('pbPreviewWrap');
    var pv = document.getElementById('pbPreview');
    if (!wrap || !pv) return;
    var avail = wrap.clientWidth || STAGE_W;
    var scale = Math.min(1, avail / STAGE_W);
    var m = 420;
    pv.querySelectorAll('.pb-el').forEach(function (n) {
      var y = parseInt(n.style.top, 10) || 0;
      var b = y + n.offsetHeight;
      if (b > m) m = b;
    });
    pv.style.transform = 'scale(' + scale + ')';
    pv.style.transformOrigin = 'top left';
    pv.style.height = m + 'px';
    wrap.style.height = (m * scale) + 'px';
  }

  /* ---------- 素材库（含删除） ---------- */
  function fillLib(container, onPick) {
    if (!container) return;
    container.innerHTML = '<span style="font-size:12px;color:#94a3b8">加载中…</span>';
    fetch(window.__PB_MEDIA__)
      .then(function (r) { return r.json(); })
      .then(function (j) {
        container.innerHTML = '';
        var items = (j && j.items) || [];
        if (!items.length) { container.innerHTML = '<span style="font-size:12px;color:#94a3b8">暂无素材，先上传</span>'; return; }
        items.forEach(function (it) {
          var cell = document.createElement('div');
          cell.className = 'pb-lib-item';
          var img = document.createElement('img');
          img.src = it.url; img.title = it.name;
          img.addEventListener('click', function () { onPick(it.url); });
          var del = document.createElement('button');
          del.className = 'pb-lib-del'; del.type = 'button'; del.textContent = '×'; del.title = '删除素材';
          del.addEventListener('click', function (e) { e.stopPropagation(); deleteMedia(it.name); });
          cell.appendChild(img); cell.appendChild(del);
          container.appendChild(cell);
        });
      })
      .catch(function () { container.innerHTML = '<span style="font-size:12px;color:#dc2626">加载失败</span>'; });
  }

  function deleteMedia(name) {
    if (!confirm('确定删除素材「' + name + '」？此操作不可撤销。')) return;
    fetch(window.__PB_DELETE__ + encodeURIComponent(name), {
      method: 'POST',
      headers: { 'X-CSRF-TOKEN': window.__PB_CSRF__ }
    })
      .then(function (r) { return r.json(); })
      .then(function (j) {
        if (j && j.ok) {
          loadLib();
          var pp = document.getElementById('pp_lib');
          if (pp) fillLib(pp, function (url) { var el = findEl(selectedId); if (el) { el.src = url; applyEl(el); } });
        } else { alert((j && j.msg) || '删除失败'); }
      })
      .catch(function () { alert('删除失败，请重试'); });
  }

  function loadLib() { fillLib(document.getElementById('pbLib'), function (url) { addImage(url); }); }

  /* ---------- 添加元素 ---------- */
  function addText() {
    var el = { id: uid(), type: 'text', x: 40, y: 40, w: 320, text: '双击编辑文字', fontSize: 20, color: '#0f172a', bold: false, align: 'left', v: false, z: nextZ() };
    elements.push(el); renderAll(); selectEl(el.id);
  }
  function addImage(url) {
    var el = { id: uid(), type: 'image', x: 40, y: 40, w: 280, src: url, align: 'left', v: false, z: nextZ() };
    elements.push(el); renderAll(); selectEl(el.id);
  }
  function addButton() {
    var el = { id: uid(), type: 'button', x: 40, y: 40, w: 200, text: '按钮', href: '#', bg: '#0ea5e9', tc: '#ffffff', size: 'md', z: nextZ() };
    elements.push(el); renderAll(); selectEl(el.id);
  }
  function addBuy() {
    var el = { id: uid(), type: 'buy', x: 40, y: 40, w: 200, z: nextZ() };
    elements.push(el); renderAll(); selectEl(el.id);
  }
  function addPrice() {
    var el = { id: uid(), type: 'price', x: 40, y: 40, w: 240, color: '#0f172a', z: nextZ() };
    elements.push(el); renderAll(); selectEl(el.id);
  }
  function addSpecs() {
    var el = { id: uid(), type: 'specs', x: 40, y: 40, w: 360, z: nextZ() };
    elements.push(el); renderAll(); selectEl(el.id);
  }

  /* 图标栏动作 */
  document.querySelectorAll('.pb-rail-btn').forEach(function (b) {
    b.addEventListener('click', function () {
      var act = b.getAttribute('data-act');
      if (act === 'material') { switchTab('material'); loadLib(); }
      else if (act === 'image') { switchTab('material'); }
      else if (act === 'text') { addText(); }
      else if (act === 'button') { addButton(); }
      else if (act === 'buy') { addBuy(); }
      else if (act === 'price') { addPrice(); }
      else if (act === 'specs') { addSpecs(); }
    });
  });

  stage.addEventListener('click', function () { selectEl(null); });

  /* ---------- 上传素材 ---------- */
  on('pbFile', 'change', function () {
    var file = this.files && this.files[0];
    if (!file) return;
    var fd = new FormData();
    fd.append('file', file);
    fetch(window.__PB_UPLOAD__, { method: 'POST', body: fd, headers: { 'X-CSRF-TOKEN': window.__PB_CSRF__ } })
      .then(function (r) { return r.json(); })
      .then(function (j) { if (j && j.ok) { addImage(j.url); loadLib(); } else alert((j && j.msg) || '上传失败'); })
      .catch(function () { alert('上传失败，请重试'); });
    this.value = '';
  });

  /* ---------- 保存：序列化到隐藏字段 ---------- */
  on('pbForm', 'submit', function () {
    var f = document.getElementById('pbLayout');
    if (f) f.value = JSON.stringify(elements);
  });

  /* ---------- 启动 ---------- */
  renderAll();
  loadLib();
  window.addEventListener('resize', fitPreview);
})();
