/* ============================================================
   管理画面JS
   - サイドメニュー開閉
   - リピーター行の追加 / 削除
   ============================================================ */
(function () {
  'use strict';

  // サイドメニュー
  var burger = document.querySelector('[data-adm-menu]');
  if (burger) {
    burger.addEventListener('click', function () {
      document.body.classList.toggle('adm-nav-open');
    });
  }

  // ブロックの折りたたみ（既定は閉じ、見出しクリックで開閉）
  // ※ 動的に追加されるスライド内のブロックにも効くよう、イベント委譲で処理
  document.addEventListener('click', function (e) {
    var btn = e.target.closest('[data-block-toggle]');
    if (!btn) return;
    var blk = btn.closest('.adm-block');
    if (!blk) return;
    blk.classList.toggle('is-collapsed');
    btn.setAttribute('aria-expanded', blk.classList.contains('is-collapsed') ? 'false' : 'true');
  });
  // デザイン画面：カラーピッカーとカラーコード入力欄を相互に同期させる。
  // ブラウザ標準のピッカーは RGB→HSL→HEX の順で開くため（この順序はHTML側から変えられない）、
  // カラーコードを直接入力・貼り付けできる欄を隣に置いている。送信されるのはコード欄の値。
  (function () {
    document.querySelectorAll('[data-color-pick]').forEach(function (pick) {
      var row = pick.parentNode;
      var hex = row ? row.querySelector('[data-color-hex]') : null;
      if (!hex) return;
      pick.addEventListener('input', function () { hex.value = pick.value; });
      hex.addEventListener('input', function () {
        var v = hex.value.trim();
        if (v && v.charAt(0) !== '#') v = '#' + v;
        if (/^#[0-9a-fA-F]{6}$/.test(v)) pick.value = v;   // 正しい形の時だけパレットへ反映
      });
      // 入力途中は自由に打たせ、離れたときに「#」を補って整える
      hex.addEventListener('blur', function () {
        var v = hex.value.trim();
        if (v && v.charAt(0) !== '#') v = '#' + v;
        if (/^#[0-9a-fA-F]{6}$/.test(v)) { hex.value = v.toLowerCase(); pick.value = hex.value; }
      });
    });
  })();

  // ?open=<id> で指定されたブロックだけ開く（パーツ追加時など）。
  // 並べ替え(↑↓)は #block-x で位置スクロールのみ＝閉じたまま。
  (function () {
    var params = new URLSearchParams(location.search);
    var openId = params.get('open');
    if (!openId) return;
    var t = document.getElementById('block-' + openId);
    if (t && t.classList.contains('adm-block')) {
      t.classList.remove('is-collapsed');
      var b = t.querySelector('[data-block-toggle]');
      if (b) b.setAttribute('aria-expanded', 'true');
      t.scrollIntoView({ block: 'start' });
      // パーツを「追加」した直後（new=1）だけ、そのブロックを3秒ハイライト。
      // 一覧モーダルが閉じて下へスクロールするため上部のフラッシュが視界外になり
      // 「追加されたことに気づけない」ため。保存(save_block)時は open= だけ＝光らせない。
      if (params.get('new') === '1') {
        t.classList.add('is-new');
        var lab = t.querySelector('.adm-block-label');
        var badge = null;
        if (lab && !lab.querySelector('.adm-new-badge')) {
          badge = document.createElement('span');
          badge.className = 'adm-new-badge';
          badge.textContent = '追加されました';
          lab.appendChild(badge);
        }
        setTimeout(function () {
          t.classList.remove('is-new');
          if (badge && badge.parentNode) badge.parentNode.removeChild(badge);
        }, 3000);
      }
    }
  })();

  // リピーター（各行は開閉式：閉じている時は「番号＋自動見出し」のバーだけ表示）
  document.querySelectorAll('[data-rep]').forEach(function (rep) {
    var rows = rep.querySelector('[data-rep-rows]');
    var addBtn = rep.querySelector('[data-rep-add]');
    var tpl = rep.querySelector('[data-rep-tpl]');   // 各リピーター固有のテンプレート
    var counter = 1000;

    // 閉じた行の見出し用テキストを決める。
    //  ①見出しに向く項目（タイトル等）に文字があればそれ。
    //  ②それも無ければ最初のテキスト項目。ただしリンク/URL系の項目は除外（「#」やURLを見出しにしない）。
    //  ③何も無ければ、このリピーターのラベル（例「写真」）＝番号と合わせて「1. 写真」のように表示。
    var repLabel = rep.getAttribute('data-rep-label') || '';
    var TITLE_KEYS = ['title', 'name', 'label', 'question', 'heading', 'text', 'body', 'role', 'caption'];
    var SKIP_KEYS = /^(url|link|href|to|src|image|img|photo|video|file|map|iframe|embed)$/i; // 見出しにしない項目キー
    function keyOfName(nm) { var m = (nm || '').match(/\[([^\]]+)\]$/); return m ? m[1] : ''; }
    function looksLikeLink(v) { return /^(https?:|\/\/|\/|#|mailto:|tel:|www\.)/i.test(v); } // 値がURL/アンカーっぽいか
    function pickTitle(row) {
      var inputs = row.querySelectorAll('[data-rep-body] input[type=text], [data-rep-body] textarea');
      var byKey = {};
      for (var i = 0; i < inputs.length; i++) { byKey[keyOfName(inputs[i].name)] = inputs[i]; }
      for (var j = 0; j < TITLE_KEYS.length; j++) {
        var inp = byKey[TITLE_KEYS[j]], v = inp ? inp.value.trim() : '';
        if (v && !looksLikeLink(v)) return v;
      }
      for (var k = 0; k < inputs.length; k++) {
        var key = keyOfName(inputs[k].name), val = inputs[k].value.trim();
        if (val && !SKIP_KEYS.test(key) && !looksLikeLink(val)) return val;
      }
      return '';
    }
    function refreshRow(row) {
      var el = row.querySelector('[data-rep-title]');
      if (el) { var t = pickTitle(row) || repLabel; el.textContent = t.length > 40 ? t.slice(0, 40) + '…' : t; }
    }
    function renumber() {
      if (!rows) return;
      var list = rows.querySelectorAll(':scope > [data-rep-row]');
      for (var i = 0; i < list.length; i++) {
        var n = list[i].querySelector('[data-rep-num]');
        if (n) n.textContent = (i + 1) + '.';
        refreshRow(list[i]);
      }
    }
    renumber();

    // 行に入力があるか判定（削除確認の要否に使う）。
    //  text/textarea/隠し値（保存済み画像・リンク）に値があれば「入力あり」。
    //  file は選択済みなら入力あり。select は既定値があるので判定から除外。
    function rowHasContent(row) {
      var body = row.querySelector('[data-rep-body]') || row;
      var els = body.querySelectorAll('input, textarea');
      for (var i = 0; i < els.length; i++) {
        var el = els[i], type = (el.type || '').toLowerCase();
        if (type === 'file') { if (el.files && el.files.length) return true; continue; }
        if (type === 'checkbox' || type === 'radio' || type === 'button' || type === 'submit') continue;
        if ((el.value || '').trim() !== '') return true;
      }
      return false;
    }

    if (addBtn && rows && tpl) {
      addBtn.addEventListener('click', function () {
        var html = tpl.innerHTML.replace(/__IDX__/g, 'new' + (counter++));
        var wrap = document.createElement('div');
        wrap.innerHTML = html.trim();
        var node = wrap.firstChild;
        rows.appendChild(node);
        if (window.cmsInitDropzones) window.cmsInitDropzones(node); // 追加行にもD&Dを適用
        if (window.cmsInitLinkFields) window.cmsInitLinkFields(node); // 追加行のリンク欄も有効化
        if (window.cmsInitRichText) window.cmsInitRichText(node); // 追加行の本文ツールバーも有効化
        renumber();
        var first = node.querySelector('[data-rep-body] input, [data-rep-body] textarea, [data-rep-body] select');
        if (first) first.focus();
      });
    }

    rep.addEventListener('click', function (e) {
      var del = e.target.closest('[data-rep-del]');
      if (del) {
        var row = del.closest('[data-rep-row]');
        if (row) {
          // 行に入力があるときだけ確認（空の行はそのまま即削除）
          if (rowHasContent(row) && !window.confirm('この行を削除しますか？')) return;
          row.remove();
        }
        renumber();
        return;
      }
      // ▲上へ移動
      var up = e.target.closest('[data-rep-up]');
      if (up) {
        var ru = up.closest('[data-rep-row]');
        var prev = ru && ru.previousElementSibling;
        if (prev && prev.hasAttribute('data-rep-row')) ru.parentNode.insertBefore(ru, prev);
        renumber();
        return;
      }
      // ▼下へ移動
      var down = e.target.closest('[data-rep-down]');
      if (down) {
        var rd = down.closest('[data-rep-row]');
        var next = rd && rd.nextElementSibling;
        if (next && next.hasAttribute('data-rep-row')) rd.parentNode.insertBefore(next, rd);
        renumber();
        return;
      }
      // 見出しバーのクリックで開閉（削除・移動ボタンのクリックは上で処理済みなので除外される）
      var head = e.target.closest('[data-rep-head]');
      if (head) { head.closest('[data-rep-row]').classList.toggle('is-collapsed'); }
    });

    // 入力中、閉じた時の見出しをリアルタイム更新
    rep.addEventListener('input', function (e) {
      var row = e.target.closest('[data-rep-row]');
      if (row) refreshRow(row);
    });
  });

  // 見出しタイプ（h_level）に連動して「装飾テキスト（任意）」の入力欄を出し分け。
  //  ・h2 のとき表示（装飾テキストは h2 のみ反映されるため）
  //  ・h3 / なし のときは非表示。ただし入力欄はDOMに残すので、入力済みの値は保持され送信もされる（h2に戻すと再表示）。
  document.querySelectorAll('select[name="f[h_level]"]').forEach(function (sel) {
    var scope = sel.closest('.adm-cardgroup') || sel.closest('form') || document;
    var deco = scope.querySelector('.fld[data-fld-key="h_deco"]');
    if (!deco) return;
    function sync() { deco.style.display = (sel.value === 'h2') ? '' : 'none'; }
    sel.addEventListener('change', sync);
    sync();
  });

  // リンク欄（field type:"link"）：ページ選択プルダウン↔自由入力↔保存値(hidden)を同期。
  //  ・プルダウンでページを選ぶ → hidden = "page:<slug>"、自由入力欄は隠す。
  //  ・「（自由にURLを入力）」を選ぶ → 自由入力欄を出し、その値を hidden に反映。
  function cmsInitLinkField(field) {
    var hidden = field.querySelector('[data-link-value]');
    var sel = field.querySelector('[data-link-page]');
    var text = field.querySelector('[data-link-text]');
    if (!hidden || !sel || !text || field._linkInit) return;
    field._linkInit = true; // 二重初期化防止
    sel.addEventListener('change', function () {
      if (sel.value) { hidden.value = sel.value; text.style.display = 'none'; }
      else { text.style.display = ''; hidden.value = text.value; text.focus(); }
    });
    text.addEventListener('input', function () { hidden.value = text.value; });
  }
  window.cmsInitLinkFields = function (scope) {
    (scope || document).querySelectorAll('[data-link-field]').forEach(cmsInitLinkField);
  };
  window.cmsInitLinkFields(document);

  // 本文欄（textarea[data-richtext]）に「太字／リンク」ツールバーを付ける。
  //  ・太字  … 選択文字を **…** で囲む（→ 公開側で <strong>）
  //  ・リンク … ページ選択 or URL入力 → [文字](リンク先) を挿入（→ 公開側で <a>）
  //  ※記法を覚えなくてもクリックで装飾できる。中身は普通のテキスト＋記号なので安全・壊れにくい。
  function rtEsc(s) { return String(s).replace(/[&<>"]/g, function (c) { return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[c]; }); }
  function rtFireInput(ta) { ta.dispatchEvent(new Event('input', { bubbles: true })); }
  function rtSurround(ta, before, after, placeholder) {
    var s = ta.selectionStart, e = ta.selectionEnd, v = ta.value;
    var sel = v.slice(s, e) || placeholder;
    ta.value = v.slice(0, s) + before + sel + after + v.slice(e);
    var ns = s + before.length, ne = ns + sel.length;
    ta.focus(); ta.setSelectionRange(ns, ne); rtFireInput(ta);
  }
  function rtInsertLink(ta, url) {
    var s = ta.selectionStart, e = ta.selectionEnd, v = ta.value;
    var label = v.slice(s, e) || 'リンク';
    var md = '[' + label + '](' + url + ')';
    ta.value = v.slice(0, s) + md + v.slice(e);
    var ns = s + 1, ne = ns + label.length;
    ta.focus(); ta.setSelectionRange(ns, ne); rtFireInput(ta);
  }
  function cmsInitRichText(ta) {
    if (ta._rtInit) return; ta._rtInit = true;
    var pages = Array.isArray(window.CMS_PAGES) ? window.CMS_PAGES : [];
    // ツールバー
    var bar = document.createElement('div'); bar.className = 'rt-toolbar';
    var bBold = document.createElement('button'); bBold.type = 'button'; bBold.className = 'adm-btn ghost sm'; bBold.textContent = '太字';
    var bLink = document.createElement('button'); bLink.type = 'button'; bLink.className = 'adm-btn ghost sm'; bLink.textContent = 'リンク';
    var tip = document.createElement('span'); tip.className = 'rt-tip'; tip.textContent = '← 下の文字列を選択した状態でボタンを押してください';
    bar.appendChild(bBold); bar.appendChild(bLink); bar.appendChild(tip);
    // リンク挿入パネル（ページ選択＋URL）
    var panel = document.createElement('div'); panel.className = 'rt-linkbar'; panel.hidden = true;
    var sel = document.createElement('select'); sel.className = 'rt-link-page';
    sel.innerHTML = '<option value="">サイト内ページを選ぶ…</option>' + pages.map(function (p) {
      return '<option value="page:' + rtEsc(p.slug) + '">' + rtEsc(p.title) + '（' + rtEsc(p.path) + '）</option>';
    }).join('');
    var url = document.createElement('input'); url.type = 'text'; url.className = 'rt-link-url'; url.placeholder = 'またはURL / #section';
    var ins = document.createElement('button'); ins.type = 'button'; ins.className = 'adm-btn primary sm'; ins.textContent = '挿入';
    panel.appendChild(sel); panel.appendChild(url); panel.appendChild(ins);
    ta.parentNode.insertBefore(bar, ta);
    ta.parentNode.insertBefore(panel, ta);
    // ボタンでの textarea のフォーカス/選択を保つ（mousedownで既定動作を止める）
    bBold.addEventListener('mousedown', function (e) { e.preventDefault(); });
    bLink.addEventListener('mousedown', function (e) { e.preventDefault(); });
    bBold.addEventListener('click', function () { rtSurround(ta, '**', '**', '太字'); });
    bLink.addEventListener('click', function () { panel.hidden = !panel.hidden; if (!panel.hidden) sel.focus(); });
    ins.addEventListener('click', function () {
      var u = sel.value || url.value.trim();
      if (!u) { sel.focus(); return; }
      rtInsertLink(ta, u);
      panel.hidden = true; sel.value = ''; url.value = '';
    });
  }
  window.cmsInitRichText = function (scope) {
    (scope || document).querySelectorAll('textarea[data-richtext]').forEach(cmsInitRichText);
  };
  window.cmsInitRichText(document);

  // アイコン選択モーダル（field type:"icon"）
  //  - 上部：よく使う厳選アイコン（カテゴリ表示）
  //  - 検索：全アイテム（Tabler全6000点・英語名）から絞り込み
  (function () {
    var icons = window.CMS_ICONS;
    if (!icons) return;
    var allNames = Array.isArray(window.CMS_ICONS_ALL) ? window.CMS_ICONS_ALL : [];
    var hasAll = allNames.length > 0;
    var allSet = {};
    allNames.forEach(function (n) { allSet[n] = 1; });

    var modal = null, activeField = null, bodyEl = null, searchEl = null;

    function nameOf(cls) { return String(cls).replace(/^ti\s+ti-/, ''); }
    // フォントが入っていれば、存在するアイコンだけ表示（誤字・未収録で空白になるのを防ぐ）
    function exists(cls) { return !hasAll || allSet[nameOf(cls)] === 1; }

    function setIcon(field, cls) {
      if (!field) return;
      var input = field.querySelector('[data-icon-input]');
      var prev  = field.querySelector('[data-icon-preview]');
      if (input) input.value = cls;
      if (prev)  prev.innerHTML = cls ? '<i class="' + cls + '"></i>' : '';
    }
    function cell(cls, label) {
      var b = document.createElement('button');
      b.type = 'button'; b.className = 'icon-cell'; b.title = label || nameOf(cls);
      b.setAttribute('data-icon-cls', cls);
      b.innerHTML = '<i class="' + cls + '"></i><span>' + (label || nameOf(cls)) + '</span>';
      return b;
    }
    function renderCurated() {
      bodyEl.innerHTML = '';
      var curatedCount = Object.keys(icons).reduce(function (a, c) { return a + icons[c].length; }, 0);
      var hint = document.createElement('div');
      hint.className = 'icon-pick-hint';
      hint.textContent = hasAll
        ? 'よく使うアイコンを表示中。ほかにも多数あります — 上の検索ボックスで全 ' + allNames.length.toLocaleString() + ' 点から探せます（英語名／例：phone, home, star）。'
        : 'よく使う ' + curatedCount + ' 点を表示中。';
      bodyEl.appendChild(hint);
      Object.keys(icons).forEach(function (cat) {
        var list = icons[cat].filter(function (p) { return exists(p[0]); });
        if (!list.length) return;
        var h = document.createElement('div');
        h.className = 'icon-cat-name'; h.textContent = cat;
        bodyEl.appendChild(h);
        var grid = document.createElement('div');
        grid.className = 'icon-grid';
        list.forEach(function (p) { grid.appendChild(cell(p[0], p[1])); });
        bodyEl.appendChild(grid);
      });
    }
    function renderSearch(q) {
      q = q.trim().toLowerCase();
      if (q === '') { renderCurated(); return; }
      bodyEl.innerHTML = '';
      var grid = document.createElement('div');
      grid.className = 'icon-grid';
      var n = 0, LIMIT = 300;
      // 全名から検索（フォント未設置時は厳選セット名で検索）
      var pool = hasAll ? allNames : [].concat.apply([], Object.keys(icons).map(function (c) {
        return icons[c].map(function (p) { return nameOf(p[0]); });
      }));
      for (var i = 0; i < pool.length && n < LIMIT; i++) {
        if (pool[i].indexOf(q) === -1) continue;
        grid.appendChild(cell('ti ti-' + pool[i], pool[i]));
        n++;
      }
      if (n === 0) {
        var none = document.createElement('div');
        none.className = 'icon-cat-name'; none.textContent = '「' + q + '」に一致するアイコンはありません';
        bodyEl.appendChild(none);
        return;
      }
      bodyEl.appendChild(grid);
    }
    function buildModal() {
      var m = document.createElement('div');
      m.className = 'icon-modal';
      var hint = hasAll ? '英語名で検索（例：phone, home, star）' : 'アイコンを選ぶ';
      m.innerHTML = '<div class="icon-modal-box">'
        + '<div class="icon-modal-head"><strong>アイコンを選ぶ</strong>'
        + '<button type="button" class="adm-btn ghost sm" data-icon-close>閉じる</button></div>'
        + '<div class="icon-modal-search"><input type="text" data-icon-search placeholder="' + hint + '"></div>'
        + '<div class="icon-modal-body"></div></div>';
      bodyEl = m.querySelector('.icon-modal-body');
      searchEl = m.querySelector('[data-icon-search]');
      renderCurated();
      searchEl.addEventListener('input', function () { renderSearch(searchEl.value); });
      m.addEventListener('click', function (e) {
        if (e.target === m || e.target.closest('[data-icon-close]')) { close(); return; }
        var c = e.target.closest('[data-icon-cls]');
        if (c && activeField) { setIcon(activeField, c.getAttribute('data-icon-cls')); close(); }
      });
      document.body.appendChild(m);
      return m;
    }
    function open(field) {
      activeField = field;
      if (!modal) modal = buildModal();
      if (searchEl) { searchEl.value = ''; renderCurated(); }
      modal.classList.add('is-open');
      if (searchEl) setTimeout(function () { searchEl.focus(); }, 30);
    }
    function close() { if (modal) modal.classList.remove('is-open'); activeField = null; }

    document.addEventListener('click', function (e) {
      var pick = e.target.closest('[data-icon-pick]');
      if (pick) { open(pick.closest('[data-icon-field]')); return; }
      var clr = e.target.closest('[data-icon-clear]');
      if (clr) { setIcon(clr.closest('[data-icon-field]'), ''); return; }
    });
    document.addEventListener('keydown', function (e) { if (e.key === 'Escape') close(); });
  })();

  // ドラッグ&ドロップ・アップロード（各 input[type=file] をドロップ領域化）
  (function () {
    function wrapOne(input) {
      if (!input || input.getAttribute('data-dz') === '1') return;
      input.setAttribute('data-dz', '1');
      var zone = document.createElement('div');
      zone.className = 'dropzone';
      var hint = document.createElement('div');
      hint.className = 'dropzone-hint';
      hint.textContent = 'ここにファイルをドラッグ＆ドロップ、または ↓';
      var name = document.createElement('div');
      name.className = 'dropzone-file';
      // input をゾーンの中へ移す
      input.parentNode.insertBefore(zone, input);
      zone.appendChild(hint);
      zone.appendChild(input);
      zone.appendChild(name);

      function showName() {
        if (!input.files || !input.files.length) { name.textContent = ''; return; }
        name.textContent = (input.multiple && input.files.length > 1)
          ? '選択中：' + input.files.length + '個のファイル'
          : '選択中：' + input.files[0].name;
      }
      input.addEventListener('change', showName);

      ['dragenter', 'dragover'].forEach(function (ev) {
        zone.addEventListener(ev, function (e) { e.preventDefault(); e.stopPropagation(); zone.classList.add('is-over'); });
      });
      ['dragleave', 'dragend', 'drop'].forEach(function (ev) {
        zone.addEventListener(ev, function (e) { e.preventDefault(); e.stopPropagation(); zone.classList.remove('is-over'); });
      });
      zone.addEventListener('drop', function (e) {
        var files = e.dataTransfer && e.dataTransfer.files;
        if (!files || !files.length) return;
        try {
          var dt = new DataTransfer();
          if (input.multiple) {
            for (var i = 0; i < files.length; i++) dt.items.add(files[i]);
          } else {
            dt.items.add(files[0]);
          }
          input.files = dt.files; // 既存のフォーム送信にそのまま乗る
        } catch (err) { return; } // 古いブラウザは「ファイルを選択」を使う
        showName();
        input.dispatchEvent(new Event('change', { bubbles: true }));
      });
    }
    function initDropzones(root) {
      (root || document).querySelectorAll('input[type="file"]').forEach(wrapOne);
    }
    window.cmsInitDropzones = initDropzones;
    initDropzones(document);
  })();
})();
