<?php
declare(strict_types=1);

require_once __DIR__ . '/_auth.php';
tpcms_require_admin();

require_once __DIR__ . '/../config.php';

// フォールバック（既存ヘルパがあればそちら優先）
if (!function_exists('tpcms_h')) {
    function tpcms_h(?string $s): string { return htmlspecialchars($s ?? '', ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('tpcms_json_read')) {
    function tpcms_json_read(string $path, $default = []) {
        if (is_file($path)) {
            $json = @file_get_contents($path);
            $data = json_decode((string)$json, true);
            if (is_array($data) || is_object($data)) return $data;
        }
        return $default;
    }
}
if (!function_exists('tpcms_json_write')) {
    function tpcms_json_write(string $path, $data): bool {
        $dir = dirname($path);
        if (!is_dir($dir) && !@mkdir($dir, 0777, true)) {
            return false;
        }
        $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
        if ($json === false) return false;

        $tmp = $path . '.tmp';
        $bytes = @file_put_contents($tmp, $json, LOCK_EX);
        if ($bytes === false || $bytes < strlen($json)) { @unlink($tmp); return false; }
        if (!@rename($tmp, $path)) { @unlink($tmp); return false; }
        @chmod($path, 0664);
        clearstatcache(true, $path);
        return true;
    }
}

// ------------------------------------------------------------
// 現在値の読み込み
// ------------------------------------------------------------
$menuPath = __DIR__ . '/../data/menu.json';
$menu = tpcms_json_read($menuPath, ['items' => []]);
$items = is_array($menu['items'] ?? null) ? $menu['items'] : [];

// ------------------------------------------------------------
// POST 保存（既存行の編集のみ）
// ------------------------------------------------------------
$saved = false;
$errors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
tpcms_require_post_csrf();
    $posted = $_POST['items'] ?? [];
    if (!is_array($posted)) $posted = [];

    // 入力→整形
    $clean = [];
    $slugs = [];
    ksort($posted); // インデックス順で安定化

    foreach ($posted as $i => $row) {
        $label = is_array($row) ? trim((string)($row['label'] ?? '')) : '';
        $slug  = is_array($row) ? trim((string)($row['slug']  ?? '')) : '';
        $show  = is_array($row) ? (isset($row['show']) ? ((string)$row['show'] === '1' ? 1 : 0) : 1) : 1;
        $show_sub  = is_array($row) ? (isset($row['show_sub']) ? ((string)$row['show_sub'] === '1' ? 1 : 0) : 1) : 1;

        // ラベル未入力の行は保存対象外（スキップ）
        if ($label === '') {
            continue;
        }
        // 検証（最小限）— <h3>見出し行は slug 空OK
        if ($slug === '' && stripos($label, '<h3') === false) {
            $errors[] = "行{$i}：スラッグは必須です。";
        }
        // スラッグ形式： (1) #about のようなページ内アンカー、または
        //               (2) 英数で始まるパス（- _ / 可）＋任意で #アンカー
        //               (3) http:// または https:// で始まる絶対URL
        // --- <h3> の見出し行は slug 空OK、それ以外は従来通り必須＋既存ルールで検証 ---
        $isHeading = (stripos($label, '<h3') !== false);
        $slug = trim((string)$slug);

        $ok = true;
        if ($slug === '') {
            // 見出し（<h3>含む）の時だけ空を許可
            if (!$isHeading) {
                $ok = false;
            }
        } else {
            // 既存ロジック相当：#アンカー / http(s):// / パス(#任意) を許可
            if ($slug[0] === '#') {
                $ok = (preg_match('~^#[A-Za-z0-9\-_]+$~', $slug) === 1);
            } elseif (preg_match('~^https?://~i', $slug)) {
                $ok = true;
            } else {
                $ok = (preg_match('~^[A-Za-z0-9][A-Za-z0-9/_\-]*(?:#[A-Za-z0-9\-_]+)?$~', $slug) === 1);
            }
        }

        if (!$ok) {
            $errors[] = 'スラッグは、#アンカー もしくは 半角英数で始まる - _ / を含むパス（任意で #アンカー可）にしてください。';
        }
        // 長さ制限（緩め）
        if (function_exists('mb_strlen')) {
            if (mb_strlen($label, 'UTF-8') > 150) $errors[] = "行{$i}：ラベルが長すぎます（150文字まで）。";
            if (mb_strlen($slug, 'UTF-8') > 60)  $errors[] = "行{$i}：スラッグが長すぎます（60文字まで）。";
        }

        // 重複スラッグ禁止（このステップでは簡易）
        if ($slug !== '') {
            if (isset($slugs[$slug])) {
                $errors[] = "行{$i}：スラッグ '{$slug}' が重複しています。";
            } else {
                $slugs[$slug] = true;
            }
        }

        $clean[] = ['label' => $label, 'slug' => $slug, 'show' => $show, 'show_sub' => $show_sub];
    }

    if (empty($errors)) {

    // --- メニューから外れたスラッグ（削除候補）を抽出 ---
    $prevSlugs = [];
    foreach ($items as $r) {
        if (is_array($r)) {
            $s = trim((string)($r['slug'] ?? ''));
            if ($s !== '') { $prevSlugs[$s] = true; }
        }
    }
    $newSlugs = [];
    foreach ($clean as $r) {
        if (is_array($r)) {
            $s = trim((string)($r['slug'] ?? ''));
            if ($s !== '') { $newSlugs[$s] = true; }
        }
    }
    $deletedSlugs = array_diff(array_keys($prevSlugs), array_keys($newSlugs));

        // 既存メニューの他キーは温存し、items だけ更新
        $menu['items'] = $clean;
        if (tpcms_json_write($menuPath, $menu)) {
            $saved = true;
            // --- menu.json 保存成功時のみ、関連ページJSONと uploads を削除 ---
            if (!empty($deletedSlugs)) {
                $active = function_exists('tpcms_active_theme') ? tpcms_active_theme() : ['theme' => 'beginner9', 'color' => 'white', 'base' => TPCMS_THEMES . '/beginner9/white'];
                $theme  = is_array($active) && is_string($active['theme'] ?? null) ? $active['theme'] : 'beginner9';
                $pagesDir = TPCMS_DATA . '/themes/' . $theme . '/pages';

                // JSON内から uploads のベース名を再帰抽出（拡張子で判定）
                $collect = function($v, array &$out) use (&$collect) {
                    if (is_array($v)) {
                        foreach ($v as $vv) { $collect($vv, $out); }
                    } elseif (is_string($v)) {
                        $base = basename($v);
                        $ext  = strtolower(pathinfo($base, PATHINFO_EXTENSION));
                        if (in_array($ext, ['jpg','jpeg','png','gif','webp','svg','mp4','webm'], true)) {
                            $out[$base] = true;
                        }
                    }
                };

                foreach ($deletedSlugs as $slug) {
                    $slug = (string)$slug;
                    $pagePath = $pagesDir . '/' . $slug . '.json';
                    if (is_file($pagePath)) {
                        $pageJson = tpcms_json_read($pagePath, []);
                        $basenames = [];
                        $collect($pageJson, $basenames);

                        // 画像・動画（basename前提）を削除
                        foreach (array_keys($basenames) as $base) {
                            $target = TPCMS_UPLOADS . '/' . $base;
                            if (is_file($target)) { @unlink($target); }
                        }
                        // ページJSONを削除
                        @unlink($pagePath);
                    }
                }
            }
            $items = $clean; // 再表示に反映
        } else {
            $errors[] = '保存に失敗しました。書き込み権限をご確認ください。';
        }
    }
}

// ------------------------------------------------------------
// HTML（GET表示＋POST後の再表示）
// ------------------------------------------------------------
?>
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>メニュー設定｜Template Party CMS</title>
  <link rel="stylesheet" href="./assets/admin.css">
</head>

<body class="admin menu">

<header>
<div>
<a href="./">ダッシュボード</a>
<a href="../" target="_blank" rel="noopener">公開側トップ</a>
</div>
<div>
<a href="./logout.php">ログアウト</a>
</div>
</header>

  <div id="container">
    <h1>メニュー設定</h1>
    <p class="muted">１つ目のチェックボックスは、メインメニュー。２つ目のチェックボックスは、予備メニュー（※テンプレによっては未使用）。<br>
    チェックの入っているものがメニューブロックに入ります。除外したい場合は、チェックを外して下さい。</p>

    <?php if (!empty($errors)): ?>
      <div class="alert error">
        <strong>エラー：</strong>
        <ul style="margin:.4rem 0 .2rem .9rem;">
          <?php foreach ($errors as $e): ?>
            <li><?= tpcms_h($e) ?></li>
          <?php endforeach; ?>
        </ul>
      </div>
    <?php elseif ($saved): ?>
      <div class="alert success">保存しました。</div>
    <?php endif; ?>

    <div class="card">
      <form method="post" action="./menu.php" id="menuForm">
      <input type="hidden" name="_csrf" value="<?= tpcms_h(tpcms_csrf_token()) ?>">

<?php if (empty($items)): ?>
      <div class="row">
          <div class="handle" title="並べ替え（次ステップ）">☰</div>
          <input type="text" name="items[0][label]" value="" placeholder="表示名（例：トップ）">
          <input type="text" name="items[0][slug]"  value="" placeholder="スラッグ（例：index）">
          <input type="hidden"   name="items[0][show]" value="0">
          <input type="checkbox" name="items[0][show]" value="1" checked>
          <input type="hidden"   name="items[0][show_sub]" value="0">
          <input type="checkbox" name="items[0][show_sub]" value="1" checked>
          <button type="button" class="btn" data-row-del>削除</button>
        </div>
<?php else: ?>
<?php foreach ($items as $i => $it):
      $label = is_array($it) ? (string)($it['label'] ?? '') : '';
      $slug  = is_array($it) ? (string)($it['slug']  ?? '') : '';
      $show  = is_array($it) ? (int)($it['show'] ?? 1) : 1;
      $show_sub  = is_array($it) ? (int)($it['show_sub'] ?? 1) : 1;
?>
        <div class="row">
          <div class="handle" title="並べ替え（次ステップ）">☰</div>
          <input type="text" name="items[<?= (int)$i ?>][label]" value="<?= tpcms_h($label) ?>" placeholder="表示名">
          <input type="text" name="items[<?= (int)$i ?>][slug]"  value="<?= tpcms_h($slug)  ?>" placeholder="スラッグ">
          <input type="hidden"   name="items[<?= (int)$i ?>][show]" value="0">
          <input type="checkbox" name="items[<?= (int)$i ?>][show]" value="1" <?= ((int)$show === 1) ? 'checked' : '' ?>>
          <input type="hidden"   name="items[<?= (int)$i ?>][show_sub]" value="0">
          <input type="checkbox" name="items[<?= (int)$i ?>][show_sub]" value="1" <?= ((int)$show_sub === 1) ? 'checked' : '' ?>>
          <button type="button" class="btn" data-row-del>削除</button>
        </div>
<?php endforeach; ?>
<?php endif; ?>

        <!-- 追加ボタン（下部） -->
        <div class="inline-block mb1rem" id="addRowBar">
          <button type="button" class="btn" id="addRowBtn">＋ 行を追加</button>
        </div>

        <!-- 新規行テンプレート（__i__ はJSで連番に置換） -->
        <template id="menuRowTpl">
          <div class="row">
            <div class="handle" title="並べ替え（次ステップ）">☰</div>
            <input type="text" name="items[__i__][label]" value="" placeholder="表示名">
            <input type="text" name="items[__i__][slug]"  value="" placeholder="スラッグ">
            <input type="hidden"   name="items[__i__][show]" value="0">
            <input type="checkbox" name="items[__i__][show]" value="1" checked>
            <input type="hidden"   name="items[__i__][show_sub]" value="0">
            <input type="checkbox" name="items[__i__][show_sub]" value="1" checked>
            <button type="button" class="btn" data-row-del>削除</button>
          </div>
        </template>

        <div>
          <button type="submit" class="btn1">保存</button>
        </div>
      </form>
    </div>
    <!--/.card-->
	  
  </div>
  <!--/container-->

<script src="./assets/admin.js"></script>

<script>
(function () {
  // DOM ready ユーティリティ
  function ready(fn) {
    if (document.readyState !== 'loading') fn();
    else document.addEventListener('DOMContentLoaded', fn, { once: true });
  }

  // 既存行の最大インデックスを取得（items[<n>][...], 数字の最大値+1を次の連番へ）
  function getNextIndex(form) {
    var max = -1;
    form.querySelectorAll('input[name^="items["]').forEach(function (el) {
      var m = el.name && el.name.match(/^items\[(\d+)\]\[/);
      if (m) {
        var n = parseInt(m[1], 10);
        if (!isNaN(n) && n > max) max = n;
      }
    });
    return max + 1;
  }

  // #menuRowTpl があればクローン、なければ手組みで生成
  function buildRow(index) {
    var tpl = document.getElementById('menuRowTpl');
    var row;

    if (tpl && 'content' in tpl && tpl.content && tpl.content.firstElementChild) {
      row = tpl.content.firstElementChild.cloneNode(true);
    } else {
      // フォールバック（クラス名は最小限。既存CSSに合わせて .row を付与）
      row = document.createElement('div');
      row.className = 'row';
      var handle = document.createElement('span');
      handle.className = 'handle';
      handle.setAttribute('aria-hidden', 'true');
      handle.textContent = '☰';
      var label = document.createElement('input');
      label.type = 'text';
      label.placeholder = 'ラベル';
      var slug = document.createElement('input');
      slug.type = 'text';
      slug.placeholder = 'スラッグ';
      row.appendChild(handle);
      row.appendChild(label);
      row.appendChild(slug);
    }

    // __i__ プレースホルダを採番 index に置換（name 属性）
    row.querySelectorAll('[name]').forEach(function(n){
      if (n.name) n.name = n.name.replace(/__i__/g, String(index));
    });

    // id 重複回避（テンプレ側に id がある場合は削除）
    row.querySelectorAll('[id]').forEach(function (n) { n.removeAttribute('id'); });

    // テキスト入力を取得（先頭=label/次=slug を想定）
    var textInputs = Array.prototype.filter.call(
      row.querySelectorAll('input'),
      function (i) { return (i.type || '').toLowerCase() === 'text'; }
    );

    var labelInput = textInputs[0] || row.querySelector('input[name$="[label]"]');
    var slugInput  = textInputs[1] || row.querySelector('input[name$="[slug]"]');

    // name を連番で強制付与（テンプレ内の既存 name を上書き）
    if (!labelInput) {
      labelInput = document.createElement('input');
      labelInput.type = 'text';
      row.appendChild(labelInput);
    }
    if (!slugInput) {
      slugInput = document.createElement('input');
      slugInput.type = 'text';
      row.appendChild(slugInput);
    }
    labelInput.name = 'items[' + index + '][label]';
    slugInput.name  = 'items[' + index + '][slug]';

    // data-idx を使っているUIがあれば更新（存在時のみ）
    if (row.hasAttribute('data-idx')) row.setAttribute('data-idx', String(index));
    row.querySelectorAll('[data-idx]').forEach(function (n) { n.setAttribute('data-idx', String(index)); });

    // 返す
    return { row: row, labelInput: labelInput };
  }

// 追加処理本体：“＋行を追加”(#addRowBar) の直前に挿入（なければ最後の .btnbar の直前）
function insertRowBeforeLastBtnbar(form, row) {
  var addBar = document.getElementById('addRowBar');
  if (addBar && addBar.parentNode) {
    addBar.parentNode.insertBefore(row, addBar);
    return;
  }
  var bars = form.querySelectorAll('.btnbar');
  var anchor = bars.length ? bars[bars.length - 1] : null;
  if (anchor && anchor.parentNode) {
    anchor.parentNode.insertBefore(row, anchor);
  } else {
    // 念のためフォールバック（btnbar が見つからない場合は末尾に追加）
    form.appendChild(row);
  }
}

  ready(function () {
    var form = document.getElementById('menuForm');
    var btn  = document.getElementById('addRowBtn');
    if (!form || !btn) return;

    btn.addEventListener('click', function (e) {
      e.preventDefault();

      // 次の連番を採番
      var idx = getNextIndex(form);

      // 行生成
      var built = buildRow(idx);

      // 挿入
      insertRowBeforeLastBtnbar(form, built.row);

      // フォーカス（1つ目のテキスト＝label に）
      try {
        built.labelInput.focus();
        built.labelInput.select && built.labelInput.select();
      } catch (_) {}
    }, false);
  });
})();
</script>

<script>
(function(){
  var form = document.getElementById('menuForm');
  if (!form) return;

  var dragRow = null;

  // ハンドルを掴んだ行だけ draggable にする
  form.addEventListener('mousedown', function(e){
    var handle = e.target.closest('.handle');
    var row = e.target.closest('.row');
    if (handle && row) {
      row.setAttribute('draggable', 'true');
    }
  });

  // ドラッグ開始
  form.addEventListener('dragstart', function(e){
    var row = e.target.closest('.row');
    if (!row) return;
    dragRow = row;
    row.classList.add('dragging');
    e.dataTransfer.effectAllowed = 'move';
    try { e.dataTransfer.setData('text/plain', ''); } catch(_){}
  });

  // ドラッグ中：マウス位置より下にある最初の .row の直前にプレビュー移動
  form.addEventListener('dragover', function(e){
    if (!dragRow) return;
    e.preventDefault();

    var rows = Array.prototype.slice.call(form.querySelectorAll('.row'));
    var y = e.clientY;

    var after = null;
    for (var i = 0; i < rows.length; i++) {
      var r = rows[i];
      if (r === dragRow) continue;
      var rect = r.getBoundingClientRect();
      var mid = rect.top + rect.height / 2;
      if (y < mid) { after = r; break; }
    }

    // 末尾扱いは「＋行を追加」バー(#addRowBar)の直前
    var addBar = document.getElementById('addRowBar');
    if (!after) {
      if (addBar && addBar.parentNode && dragRow !== addBar) {
        addBar.parentNode.insertBefore(dragRow, addBar);
      }
    } else {
      after.parentNode.insertBefore(dragRow, after);
    }
  });

  // ドロップ確定
  form.addEventListener('drop', function(e){
    if (!dragRow) return;
    e.preventDefault();
  });

  // 終了：draggable解除＆インデックス振り直し
  form.addEventListener('dragend', function(){
    if (!dragRow) return;
    dragRow.classList.remove('dragging');
    dragRow.removeAttribute('draggable');
    dragRow = null;
    reindexRows();
  });

  // 並び順に合わせて name="items[<i>][label|slug]" を振り直し
  function reindexRows(){
    var rows = Array.prototype.slice.call(form.querySelectorAll('.row'));
    rows.forEach(function(row, i){
      row.querySelectorAll('input[name^="items["]').forEach(function(inp){
        if (/\[label\]$/.test(inp.name)) {
          inp.name = 'items[' + i + '][label]';
        } else if (/\[slug\]$/.test(inp.name)) {
          inp.name = 'items[' + i + '][slug]';
        }
      });
    });
  }
})();
</script>

<script>
document.addEventListener('click', function(e){
  var btn = e.target.closest('[data-row-del]');
  if (!btn) return;
  var row = btn.closest('.row');
  if (!row) return;
  // その場でDOMから取り除く（POST対象から外れる → 保存で確定反映）
  row.parentNode.removeChild(row);
}, false);
</script>

</body>
</html>
