<?php
declare(strict_types=1);
require_once __DIR__ . '/_bootstrap.php';
require_login();

/* ============================================================
 *  POST 処理
 * ============================================================ */
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    require_post_csrf();
    $action = (string)($_POST['action'] ?? '');

    if ($action === 'add_item') {
        $label = trim((string)($_POST['label'] ?? ''));
        if ($label === '') {
            flash_set('ラベルを入力してください。', 'err');
        } else {
            [$type, $link, $parent] = menu_read_target($_POST);
            $isBtn = !empty($_POST['is_button']) ? 1 : 0;
            $maxSort = (int)db()->query("SELECT COALESCE(MAX(sort),0) FROM menu_items")->fetchColumn();
            db()->prepare("INSERT INTO menu_items(label,link_type,link,parent_id,show_pc,show_mobile,is_button,sort) VALUES(?,?,?,?,?,?,?,?)")
                ->execute([$label, $type, $link, $parent, 1, 1, $isBtn, $maxSort + 1]);
            flash_set('「' . $label . '」を追加しました。');
        }
        redirect('/admin/menu.php');
    }

    if ($action === 'save_item') {
        $id = (int)($_POST['id'] ?? 0);
        $it = menu_find($id);
        if ($it) {
            $label = trim((string)($_POST['label'] ?? ''));
            [$type, $link, $parent] = menu_read_target($_POST);
            // 自分自身や、子を持つ項目を子にしない（2階層まで）
            if ($parent === $id) $parent = null;
            $showPc = !empty($_POST['show_pc']) ? 1 : 0;
            $showMb = !empty($_POST['show_mobile']) ? 1 : 0;
            $isBtn  = !empty($_POST['is_button']) ? 1 : 0;
            db()->prepare("UPDATE menu_items SET label=?, link_type=?, link=?, parent_id=?, show_pc=?, show_mobile=?, is_button=? WHERE id=?")
                ->execute([$label, $type, $link, $parent, $showPc, $showMb, $isBtn, $id]);
            flash_set('保存しました。');
        }
        redirect('/admin/menu.php');
    }

    if ($action === 'delete_item') {
        $id = (int)($_POST['id'] ?? 0);
        // 子を親なしに引き上げてから削除
        db()->prepare("UPDATE menu_items SET parent_id=NULL WHERE parent_id=?")->execute([$id]);
        db()->prepare("DELETE FROM menu_items WHERE id=?")->execute([$id]);
        flash_set('削除しました。');
        redirect('/admin/menu.php');
    }

    if ($action === 'move_item') {
        menu_move((int)($_POST['id'] ?? 0), (string)($_POST['dir'] ?? ''));
        redirect('/admin/menu.php');
    }
}

/** $_POST からリンク種別・リンク先・親を読む */
function menu_read_target(array $post): array {
    $type = (string)($post['link_type'] ?? 'page');
    if (!in_array($type, ['page', 'url', 'anchor', 'heading'], true)) $type = 'page';
    $link = '';
    if ($type === 'page')        $link = (string)($post['link_page'] ?? '');
    elseif ($type === 'url')     $link = trim((string)($post['link_url'] ?? ''));
    elseif ($type === 'anchor')  $link = trim((string)($post['link_anchor'] ?? ''));
    $parentRaw = (string)($post['parent_id'] ?? '');
    $parent = ($parentRaw === '' || $parentRaw === '0') ? null : (int)$parentRaw;
    return [$type, $link, $parent];
}

/** 同じ親グループ内で並べ替え */
function menu_move(int $id, string $dir): void {
    $it = menu_find($id);
    if (!$it) return;
    $pid = $it['parent_id'];
    $where = $pid === null ? "parent_id IS NULL" : "parent_id = " . (int)$pid;
    $rows = db()->query("SELECT id,sort FROM menu_items WHERE $where ORDER BY sort,id")->fetchAll();
    $pos = null;
    foreach ($rows as $i => $r) { if ((int)$r['id'] === $id) { $pos = $i; break; } }
    if ($pos === null) return;
    $swap = $dir === 'up' ? $pos - 1 : $pos + 1;
    if ($swap < 0 || $swap >= count($rows)) return;
    $u = db()->prepare("UPDATE menu_items SET sort=? WHERE id=?");
    $u->execute([(int)$rows[$swap]['sort'], (int)$rows[$pos]['id']]);
    $u->execute([(int)$rows[$pos]['sort'], (int)$rows[$swap]['id']]);
}

/* ============================================================
 *  描画
 * ============================================================ */
$items = menu_all();
$tops  = array_values(array_filter($items, fn($i) => $i['parent_id'] === null || $i['parent_id'] === ''));
$childrenOf = [];
foreach ($items as $it) {
    if ($it['parent_id'] !== null && $it['parent_id'] !== '') $childrenOf[(int)$it['parent_id']][] = $it;
}
$pages = page_all();
// サイド型(2カラム)フレームのときだけ「見出し（リンクなし）」を使えるようにする（1カラムでは選択肢も既存見出しも隠す）
$isSidebar = !empty((frame_all()[active_frame_key()] ?? [])['menu_sidebar']);

/** 全ページのパーツから「アンカーID」を集めて、ページ内リンクのプルダウン候補を作る */
function menu_collect_anchors(): array {
    $out = [];
    foreach (page_all() as $p) {
        $slug = (string)($p['slug'] ?? '');
        foreach (blocks_of((int)$p['id']) as $blk) {
            $data = json_decode((string)($blk['data'] ?? '{}'), true);
            if (!is_array($data)) continue;
            $a = preg_replace('/[^A-Za-z0-9_\-]/', '', trim((string)($data['anchor'] ?? '')));
            if ($a === '') continue;
            // ホーム（LP）は同一ページ内ジャンプ＝「#id」（スムーススクロールが効く）。他ページは「/?p=slug#id」。
            $href = ($slug === '' || $slug === 'home') ? ('#' . $a) : (page_url($slug) . '#' . $a);
            $out[] = ['href' => $href, 'label' => ((string)($p['title'] ?? $slug)) . '：' . $a];
        }
    }
    return $out;
}
$anchors = menu_collect_anchors();

/** リンク先の説明テキスト */
function menu_target_label(array $it, array $pages): string {
    $type = $it['link_type'];
    if ($type === 'page') {
        foreach ($pages as $p) if ($p['slug'] === $it['link']) return 'ページ：' . $p['title'];
        return 'ページ：' . $it['link'];
    }
    if ($type === 'url')     return 'URL：' . $it['link'];
    if ($type === 'anchor')  return 'ページ内：' . $it['link'];
    return '見出し（リンクなし）';
}

/** 1項目の編集フォーム（追加・編集共用の入力部分） */
function menu_fields_html(array $it, array $pages, array $tops, bool $allowHeading = false, array $anchors = []): string {
    // 追加フォーム等、未設定キーを既定値で補完（PHP8のUndefined key警告回避）
    $it += ['id' => 0, 'label' => '', 'link_type' => 'page', 'link' => '', 'parent_id' => null, 'show_pc' => 1, 'show_mobile' => 1, 'is_button' => 0];
    $type = $it['link_type'] ?? 'page';
    $h = '';
    // ラベル
    $h .= '<div class="fld"><label class="fld-label">メニュー名（表示文字）</label>'
        . '<input type="text" name="label" placeholder="例：サービス紹介" value="' . h((string)($it['label'] ?? '')) . '"></div>';
    // リンク種別
    $h .= '<div class="fld"><label class="fld-label">リンクの種類</label>'
        . '<select name="link_type" data-link-type>';
    $linkTypeOpts = ['page' => 'サイト内のページ', 'url' => '外部URL', 'anchor' => 'ページ内リンク（#）'];
    if ($allowHeading || $type === 'heading') $linkTypeOpts['heading'] = '見出し（リンクなし）'; // サイド型のみ。既に見出しの項目は編集できるよう常に出す
    foreach ($linkTypeOpts as $v => $lbl) {
        $h .= '<option value="' . $v . '"' . ($type === $v ? ' selected' : '') . '>' . h($lbl) . '</option>';
    }
    $h .= '</select></div>';
    // ページ選択
    $h .= '<div class="fld" data-link="page"><label class="fld-label">リンク先を選択</label><select name="link_page">';
    foreach ($pages as $p) {
        $sel = ($type === 'page' && $it['link'] === $p['slug']) ? ' selected' : '';
        $h .= '<option value="' . h($p['slug']) . '"' . $sel . '>' . h($p['title']) . '（/' . h($p['slug']) . '）</option>';
    }
    $h .= '</select></div>';
    // 外部URL
    $h .= '<div class="fld" data-link="url"><label class="fld-label">外部URL</label>'
        . '<input type="text" name="link_url" placeholder="https://..." value="' . h($type === 'url' ? (string)$it['link'] : '') . '"></div>';
    // アンカー（ページ内リンク）：各パーツの「アンカーID」から集めた飛び先をプルダウンで選ぶ
    $curAnchor = ($type === 'anchor') ? (string)$it['link'] : '';
    $h .= '<div class="fld" data-link="anchor"><label class="fld-label">ジャンプ先（ページ内リンク）</label>';
    if ($anchors) {
        $h .= '<select name="link_anchor"><option value="">（選択してください）</option>';
        $found = false;
        foreach ($anchors as $a) {
            $sel = ($curAnchor !== '' && $curAnchor === $a['href']) ? ' selected' : '';
            if ($sel !== '') $found = true;
            $h .= '<option value="' . h($a['href']) . '"' . $sel . '>' . h($a['label']) . '</option>';
        }
        if ($curAnchor !== '' && !$found) { // 一覧に無い既存値（旧データ等）は保持
            $h .= '<option value="' . h($curAnchor) . '" selected>現在の値：' . h($curAnchor) . '</option>';
        }
        $h .= '</select>';
    } else {
        // 飛び先が未設定：現在値はhiddenで保持しつつ、設定方法を案内
        $h .= '<input type="hidden" name="link_anchor" value="' . h($curAnchor) . '">'
            . '<span class="fld-hint">まだジャンプ先がありません。各ページのパーツの「アンカーID（ページ内リンクの飛び先）」欄で先に飛び先を設定してください。</span>';
    }
    $h .= '</div>';
    // 親メニュー
    $h .= '<div class="fld" data-not-heading><label class="fld-label">親メニュー（ドロップダウンの子にする場合）</label><select name="parent_id">';
    $h .= '<option value="">なし（トップ階層）</option>';
    foreach ($tops as $t) {
        if ((int)($t['id'] ?? 0) === (int)($it['id'] ?? -1)) continue; // 自分は親にしない
        $sel = ((string)($it['parent_id'] ?? '') === (string)$t['id']) ? ' selected' : '';
        $h .= '<option value="' . (int)$t['id'] . '"' . $sel . '>' . h($t['label']) . '</option>';
    }
    $h .= '</select></div>';
    // 表示場所
    $pc = !isset($it['show_pc']) || $it['show_pc'] ? 'checked' : '';
    $mb = !isset($it['show_mobile']) || $it['show_mobile'] ? 'checked' : '';
    $h .= '<div class="fld fld-check" data-not-heading><label><input type="checkbox" name="show_pc" value="1" ' . $pc . '> パソコンのメインメニューに表示</label></div>';
    $h .= '<div class="fld fld-check" data-not-heading><label><input type="checkbox" name="show_mobile" value="1" ' . $mb . '> スマホの開閉メニューに表示</label></div>';
    // ボタン風（li に class="btn"）
    $btn = !empty($it['is_button']) ? 'checked' : '';
    $h .= '<div class="fld fld-check" data-not-heading><label><input type="checkbox" name="is_button" value="1" ' . $btn . '> ボタン風に表示（「お問い合わせ」等を目立たせる）</label></div>';
    return $h;
}

admin_header('メニュー管理', 'menu');
?>
<h1 class="adm-h1">メニュー管理</h1>
<?php flash_render(); ?>
<div class="adm-guide">
  ここは<strong>ナビに並べるリンクを編集</strong>する場所です。メニュー項目は「既存ページへのリンク」。
  <strong>新しいページ自体は<a href="<?= h(url('/admin/index.php#pages')) ?>">ダッシュボード</a>で作成</strong>します。
  親メニューを選ぶとドロップダウンの子になります。
  <a href="<?= h(url('/')) ?>" target="_blank" rel="noopener">サイトを表示 ↗</a>
</div>
<?php if ($isSidebar): ?>
<div class="adm-guide" style="background:#eff6ff;border-color:#bfdbfe;">
  💡 このフレームは<strong>サイドメニュー型</strong>です。「リンクの種類」で<strong>「見出し（リンクなし）」</strong>を選ぶと、メニューを<strong>見出しでグループ分け</strong>できます（リンクにならない区切りラベル）。長いメニューが見やすくなります。
</div>
<?php endif; ?>

<?php if (!$tops): ?>
  <p class="adm-empty">メニュー項目がありません。下から追加してください。</p>
<?php endif; ?>

<?php
$render_item_card = function (array $it, bool $isChild) use ($pages, $tops, $isSidebar, $anchors) {
    $kidCount = 0; // 表示用
    ?>
  <div class="adm-block is-collapsed <?= $isChild ? 'menu-child' : '' ?>" id="mi-<?= (int)$it['id'] ?>">
    <div class="adm-block-head">
      <button type="button" class="adm-block-label" data-block-toggle aria-expanded="false">
        <span class="block-chevron" aria-hidden="true">▶</span>
        <?= $isChild ? '└ ' : '' ?><?= h($it['label']) ?>
        <span class="menu-target-badge"><?= h(menu_target_label($it, $pages)) ?></span>
      </button>
      <span class="adm-block-tools">
        <form method="post" style="display:inline">
          <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
          <input type="hidden" name="action" value="move_item"><input type="hidden" name="id" value="<?= (int)$it['id'] ?>">
          <button class="adm-btn ghost sm" name="dir" value="up">↑</button>
          <button class="adm-btn ghost sm" name="dir" value="down">↓</button>
        </form>
        <form method="post" style="display:inline" onsubmit="return confirm('この項目を削除しますか？');">
          <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
          <input type="hidden" name="action" value="delete_item"><input type="hidden" name="id" value="<?= (int)$it['id'] ?>">
          <button class="adm-btn danger sm" type="submit">削除</button>
        </form>
      </span>
    </div>
    <form method="post" class="adm-form menu-form">
      <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
      <input type="hidden" name="action" value="save_item">
      <input type="hidden" name="id" value="<?= (int)$it['id'] ?>">
      <?= menu_fields_html($it, $pages, $tops, $isSidebar, $anchors) ?>
      <button class="adm-btn primary" type="submit">保存</button>
    </form>
  </div>
<?php
};

foreach ($tops as $t) {
    if (!$isSidebar && ($t['link_type'] ?? '') === 'heading') continue; // 見出しはサイド型フレームのときだけ一覧に出す（データは保持）
    $render_item_card($t, false);
    foreach (($childrenOf[(int)$t['id']] ?? []) as $c) {
        if (!$isSidebar && ($c['link_type'] ?? '') === 'heading') continue;
        $render_item_card($c, true);
    }
}
?>

<!-- 追加（既定で閉じる） -->
<div class="adm-block is-collapsed adm-add-card" id="add-menu-item">
  <div class="adm-block-head">
    <button type="button" class="adm-block-label" data-block-toggle aria-expanded="false">
      <span class="block-chevron" aria-hidden="true">▶</span>＋ メニュー項目を追加
    </button>
  </div>
  <form method="post" class="adm-form menu-form">
    <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
    <input type="hidden" name="action" value="add_item">
    <?= menu_fields_html(['link_type' => 'page', 'show_pc' => 1, 'show_mobile' => 1], $pages, $tops, $isSidebar, $anchors) ?>
    <button class="adm-btn primary" type="submit">追加</button>
  </form>
</div>

<script>
/* リンク種別に応じて入力欄を出し分け */
(function () {
  document.querySelectorAll('.menu-form').forEach(function (form) {
    var sel = form.querySelector('[data-link-type]');
    if (!sel) return;
    function sync() {
      var v = sel.value;
      form.querySelectorAll('[data-link]').forEach(function (el) {
        el.style.display = (el.getAttribute('data-link') === v) ? '' : 'none';
      });
      // 見出し（リンクなし）のときは、親メニュー欄と3つのチェックボックスを隠す
      // （見出しはボタン化せず・PC/スマホ両方に出力するため、既定のまま保存すればよい）
      form.querySelectorAll('[data-not-heading]').forEach(function (el) {
        el.style.display = (v === 'heading') ? 'none' : '';
      });
    }
    sel.addEventListener('change', sync);
    sync();
  });
})();
</script>

<?php admin_footer(); ?>
