{% extends 'admin/base.html' %}

{% block title %}{{ t('menus.title') }}{% endblock %}

{% block content %}
<div class="page-header page-header--with-action">
    <div class="page-header__content">
        <h2>📋 {{ t('menus.title') }}</h2>
        <p>{{ t('menus.subtitle') }}</p>
    </div>
    <button type="button" class="btn btn-primary" onclick="saveActiveMenu()">💾 {{ t('menus.save_menu') }}</button>
</div>

<!-- Location Tabs: Header / Footer -->
<div class="menu-tabs">
    <button class="menu-tab active" data-loc="header" onclick="switchLocationTab('header', event)">📌 {{ t('menus.header_menu') }}</button>
    <button class="menu-tab" data-loc="footer" onclick="switchLocationTab('footer', event)">📎 {{ t('menus.footer_menu') }}</button>
</div>

<!-- ============================================================ -->
<!-- HEADER MENU FORM                                             -->
<!-- ============================================================ -->
<div id="header-form" class="menu-form">
    <div class="info-box">
        <p>💡 {{ t('menus.header_info')|safe }}</p>
    </div>

    <form method="POST" id="header-menu-form">
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
        <input type="hidden" name="menu_location" value="header">
        <input type="hidden" name="menu_structure" id="header-menu-structure" value="">

        {# ── Recursive builder row: renders an item and its subtree up to
     config.MENU_MAX_DEPTH tiers. Depth 0 rows use temp id 'srv-<id>',
     nested rows 'srv-child-<id>' (matches custom_links_data keys). ── #}
{% macro builder_row(item, location, parent_temp, depth) %}
{%- set tid = ('srv-' ~ item.id) if depth == 0 else ('srv-child-' ~ item.id) -%}
<div class="menu-item-row"
     draggable="true"
     data-temp-id="{{ tid }}"
     data-type="{{ item.page_type or 'page' }}"
     data-id="{% if item.page_type == 'custom' %}{{ tid }}{% else %}{{ item.page_id or item.post_id or '' }}{% endif %}"
     data-parent="{{ parent_temp }}"
     data-translation-group="{{ (item.page.translation_group if item.page else (item.post.translation_group if item.post else '')) or '' }}"
     ondragstart="onItemDragStart(event)"
     ondragend="onItemDragEnd(event)">
    <span class="menu-item-row__handle" title="{{ t('menus.drag_to_reorder') }}">⠿</span>
    <span class="menu-item-row__label">{{ item.label }}</span>
    <span class="menu-item-row__lang">{{ item.language|upper }}</span>
    <div class="menu-item-row__actions">
        <button type="button" class="menu-item-row__add-child menu-item-row__nest"
                onclick="nestItem(this, '{{ location }}')"
                title="{{ t('menus.add_submenu_item') }}">⤵ {{ t('menus.child_item') }}</button>
        <button type="button" class="menu-item-row__add-child menu-item-row__unnest"
                onclick="unnestItem(this, '{{ location }}')"
                title="{{ t('menus.parent_item') }}">⤴ {{ t('menus.parent_item') }}</button>
        {% if item.page_type == 'custom' %}
        <button type="button" class="menu-item-row__edit"
                onclick="editCustomLink(this, '{{ location }}')"
                title="{{ t('menus.edit_link') }}">✏️</button>
        {% endif %}
        <button type="button" class="menu-item-row__remove"
                onclick="removeItem(this, '{{ location }}')"
                title="{{ t('menus.remove_item') }}">✕</button>
    </div>
</div>
{% set kids = parent_map[location].get(item.id) %}
{% if kids and depth + 1 < config.MENU_MAX_DEPTH %}
<div class="menu-submenu" data-parent-temp="{{ tid }}">
    {% for child in kids %}{{ builder_row(child, location, tid, depth + 1) }}{% endfor %}
</div>
{% endif %}
{% endmacro %}

<div class="menu-builder-layout">

            <!-- ── TOP: visual menu builder ───────────────────────── -->
            <div class="menu-builder" id="header-builder">
                <div class="menu-builder__title">{{ t('menus.header_menu') }}</div>
                <div class="menu-builder__note">{{ t('menus.drag_to_reorder') }} · {{ t('menus.drag_to_nest') }}</div>

                <div class="menu-builder__list" id="header-builder-list"
                     ondragover="onBuilderDragOver(event, 'header')"
                     ondrop="onBuilderDrop(event, 'header')"
                     ondragleave="onBuilderDragLeave(event, 'header')">

                    {% if header_items %}
                        {% for item in header_items %}{{ builder_row(item, 'header', '', 0) }}{% endfor %}
                    {% else %}
                    <div class="menu-builder__empty" id="header-builder-empty">
                        <p>{{ t('menus.no_menu_items') }}</p>
                    </div>
                    {% endif %}
                </div>

                <div class="menu-builder__footer">
                    <p class="menu-builder__submenu-note">{{ t('menus.submenu_note') }}</p>
                    <p class="menu-builder__submenu-note">{{ t('menus.anchor_links_hint') }}</p>
                </div>
            </div><!-- /.menu-builder -->

            <!-- ── BOTTOM: content picker ──────────────────────────── -->
            <div class="menu-picker">
                <div class="content-tabs">
                    <button type="button" class="content-tab active" data-tab="pages" onclick="switchContentTab('header', 'pages', event)">📄 {{ t('sidebar.pages') }}</button>
                    <button type="button" class="content-tab" data-tab="posts" onclick="switchContentTab('header', 'posts', event)">📝 {{ t('sidebar.posts') }}</button>
                    <button type="button" class="content-tab" data-tab="custom" onclick="switchContentTab('header', 'custom', event)">🔗 {{ t('menus.custom_links') }}</button>
                </div>

                <!-- Pages panel -->
                <div id="header-pages-panel" class="content-panel active">
                    <div class="filter-bar">
                        <input type="text" id="header-pages-search" placeholder="🔍 {{ t('pages.search_placeholder') }}">
                        <select id="header-pages-lang">
                            <option value="all">{{ t('menus.all_languages') }}</option>
                            {% for lang in active_languages %}
                            <option value="{{ lang.code }}">{{ lang.name }}</option>
                            {% endfor %}
                        </select>
                        <select id="header-pages-sort">
                            <option value="">{{ t('table.title') }}</option>
                            <option value="title-asc">{{ t('table.title') }} A→Z</option>
                            <option value="title-desc">{{ t('table.title') }} Z→A</option>
                        </select>
                        <select id="header-pages-date">
                            <option value="">{{ t('menus.published') }}</option>
                            <option value="date-desc">{{ t('table.newest_first') }}</option>
                            <option value="date-asc">{{ t('table.oldest_first') }}</option>
                        </select>
                        <span class="selected-counter" id="header-pages-counter"></span>
                    </div>
                    <table class="content-table" id="header-pages-table">
                        <thead>
                            <tr>
                                <th class="cb-cell">☑</th>
                                <th>{{ t('table.title') }}</th>
                                <th>{{ t('menus.menu_label') }}</th>
                                <th>{{ t('menus.lang') }}</th>
                                <th>{{ t('menus.published') }}</th>
                            </tr>
                        </thead>
                        <tbody></tbody>
                    </table>
                </div>

                <!-- Posts panel -->
                <div id="header-posts-panel" class="content-panel">
                    <div class="filter-bar">
                        <input type="text" id="header-posts-search" placeholder="🔍 {{ t('posts.search_placeholder') }}">
                        <select id="header-posts-lang">
                            <option value="all">{{ t('menus.all_languages') }}</option>
                            {% for lang in active_languages %}
                            <option value="{{ lang.code }}">{{ lang.name }}</option>
                            {% endfor %}
                        </select>
                        <select id="header-posts-sort">
                            <option value="">{{ t('table.title') }}</option>
                            <option value="title-asc">{{ t('table.title') }} A→Z</option>
                            <option value="title-desc">{{ t('table.title') }} Z→A</option>
                        </select>
                        <select id="header-posts-date">
                            <option value="">{{ t('menus.published') }}</option>
                            <option value="date-desc">{{ t('table.newest_first') }}</option>
                            <option value="date-asc">{{ t('table.oldest_first') }}</option>
                        </select>
                        <span class="selected-counter" id="header-posts-counter"></span>
                    </div>
                    <table class="content-table" id="header-posts-table">
                        <thead>
                            <tr>
                                <th class="cb-cell">☑</th>
                                <th>{{ t('table.title') }}</th>
                                <th>{{ t('menus.menu_label') }}</th>
                                <th>{{ t('menus.lang') }}</th>
                                <th>{{ t('menus.published') }}</th>
                            </tr>
                        </thead>
                        <tbody></tbody>
                    </table>
                </div>

                <!-- Custom Links panel -->
                <div id="header-custom-panel" class="content-panel">
                    <table class="content-table" id="header-custom-table">
                        <thead>
                            <tr>
                                <th class="cb-cell">🔗</th>
                                <th>{{ t('menus.custom_url_header') }}</th>
                                <th>{{ t('menus.menu_label') }}</th>
                                <th>{{ t('menus.lang') }}</th>
                                <th>{{ t('menus.pick_file') }}</th>
                            </tr>
                        </thead>
                        <tbody>
                            {% for lang in active_languages %}
                            <tr class="row-checked" data-lang="{{ lang.code }}">
                                <td class="cb-cell">🔗</td>
                                <td>
                                    <input type="text" class="label-input custom-links__url"
                                           data-lang="{{ lang.code }}"
                                           placeholder="{{ t('menus.custom_url_placeholder') }}">
                                </td>
                                <td>
                                    <input type="text" class="label-input custom-links__label"
                                           data-lang="{{ lang.code }}"
                                           placeholder="{{ t('menus.custom_label_placeholder') }}">
                                </td>
                                <td><span class="lang-badge">{{ lang.code|upper }}</span></td>
                                <td>
                                    <select class="label-input custom-links__file-picker" data-lang="{{ lang.code }}">
                                        <option value="">📎 {{ t('menus.pick_file') }}</option>
                                        {% for f in files_list %}
                                        <option value="/{{ f.download_slug }}">{{ f.title or f.original_filename or f.filename }}</option>
                                        {% endfor %}
                                    </select>
                                </td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                    <div class="custom-links__bottom">
                        <label class="custom-links__target-label">
                            <input type="checkbox" class="custom-links__target">
                            {{ t('menus.open_new_window') }}
                        </label>
                        <button type="button" class="btn btn-primary"
                                onclick="addCustomLink('header')">
                            ➕ {{ t('menus.add_to_menu') }}
                        </button>
                    </div>
                </div>
            </div><!-- /.menu-picker -->

        </div><!-- /.menu-builder-layout -->
    </form>
</div><!-- /#header-form -->
<div class="pagination-footer" id="header-pages-pagination"></div>
<div class="pagination-footer" id="header-posts-pagination" style="display:none"></div>


<!-- ============================================================ -->
<!-- FOOTER MENU FORM                                             -->
<!-- ============================================================ -->
<div id="footer-form" class="menu-form" style="display:none;">
    <div class="info-box">
        <p>💡 {{ t('menus.footer_info') }}</p>
    </div>

    <form method="POST" id="footer-menu-form">
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
        <input type="hidden" name="menu_location" value="footer">
        <input type="hidden" name="menu_structure" id="footer-menu-structure" value="">

        <div class="menu-builder-layout">

            <!-- ── TOP: visual menu builder ───────────────────────── -->
            <div class="menu-builder" id="footer-builder">
                <div class="menu-builder__title">{{ t('menus.footer_menu') }}</div>
                <div class="menu-builder__note">{{ t('menus.drag_to_reorder') }}</div>

                <div class="menu-builder__list" id="footer-builder-list"
                     ondragover="onBuilderDragOver(event, 'footer')"
                     ondrop="onBuilderDrop(event, 'footer')"
                     ondragleave="onBuilderDragLeave(event, 'footer')">

                    {% if footer_items %}
                        {% for item in footer_items %}
                        <div class="menu-item-row"
                             draggable="true"
                             data-temp-id="srv-{{ item.id }}"
                             data-type="{{ item.page_type or 'page' }}"
                             data-id="{% if item.page_type == 'custom' %}srv-{{ item.id }}{% else %}{{ item.page_id or item.post_id or '' }}{% endif %}"
                             data-parent=""
                             data-translation-group="{{ (item.page.translation_group if item.page else (item.post.translation_group if item.post else '')) or '' }}"
                             ondragstart="onItemDragStart(event)"
                             ondragend="onItemDragEnd(event)">
                            <span class="menu-item-row__handle">⠿</span>
                            <span class="menu-item-row__label">{{ item.label }}</span>
                            <span class="menu-item-row__lang">{{ item.language|upper }}</span>
                            <div class="menu-item-row__actions">
                                {% if item.page_type == 'custom' %}
                                <button type="button" class="menu-item-row__edit"
                                        onclick="editCustomLink(this, 'footer')"
                                        title="{{ t('menus.edit_link') }}">✏️</button>
                                {% endif %}
                                <button type="button" class="menu-item-row__remove"
                                        onclick="removeItem(this, 'footer')"
                                        title="{{ t('menus.remove_item') }}">✕</button>
                            </div>
                        </div>
                        {% endfor %}
                    {% else %}
                    <div class="menu-builder__empty" id="footer-builder-empty">
                        <p>{{ t('menus.no_menu_items') }}</p>
                    </div>
                    {% endif %}
                </div>

                <div class="menu-builder__footer">
                    <p class="menu-builder__submenu-note">{{ t('menus.submenu_note') }}</p>
                    <p class="menu-builder__submenu-note">{{ t('menus.anchor_links_hint') }}</p>
                </div>
            </div><!-- /.menu-builder -->

            <!-- ── BOTTOM: content picker ──────────────────────────── -->
            <div class="menu-picker">
                <div class="content-tabs">
                    <button type="button" class="content-tab active" data-tab="pages" onclick="switchContentTab('footer', 'pages', event)">📄 {{ t('sidebar.pages') }}</button>
                    <button type="button" class="content-tab" data-tab="posts" onclick="switchContentTab('footer', 'posts', event)">📝 {{ t('sidebar.posts') }}</button>
                    <button type="button" class="content-tab" data-tab="custom" onclick="switchContentTab('footer', 'custom', event)">🔗 {{ t('menus.custom_links') }}</button>
                </div>

                <!-- Pages panel -->
                <div id="footer-pages-panel" class="content-panel active">
                    <div class="filter-bar">
                        <input type="text" id="footer-pages-search" placeholder="🔍 {{ t('pages.search_placeholder') }}">
                        <select id="footer-pages-lang">
                            <option value="all">{{ t('menus.all_languages') }}</option>
                            {% for lang in active_languages %}
                            <option value="{{ lang.code }}">{{ lang.name }}</option>
                            {% endfor %}
                        </select>
                        <select id="footer-pages-sort">
                            <option value="">{{ t('table.title') }}</option>
                            <option value="title-asc">{{ t('table.title') }} A→Z</option>
                            <option value="title-desc">{{ t('table.title') }} Z→A</option>
                        </select>
                        <select id="footer-pages-date">
                            <option value="">{{ t('menus.published') }}</option>
                            <option value="date-desc">{{ t('table.newest_first') }}</option>
                            <option value="date-asc">{{ t('table.oldest_first') }}</option>
                        </select>
                        <span class="selected-counter" id="footer-pages-counter"></span>
                    </div>
                    <table class="content-table" id="footer-pages-table">
                        <thead>
                            <tr>
                                <th class="cb-cell">☑</th>
                                <th>{{ t('table.title') }}</th>
                                <th>{{ t('menus.menu_label') }}</th>
                                <th>{{ t('menus.lang') }}</th>
                                <th>{{ t('menus.published') }}</th>
                            </tr>
                        </thead>
                        <tbody></tbody>
                    </table>
                </div>

                <!-- Posts panel -->
                <div id="footer-posts-panel" class="content-panel">
                    <div class="filter-bar">
                        <input type="text" id="footer-posts-search" placeholder="🔍 {{ t('posts.search_placeholder') }}">
                        <select id="footer-posts-lang">
                            <option value="all">{{ t('menus.all_languages') }}</option>
                            {% for lang in active_languages %}
                            <option value="{{ lang.code }}">{{ lang.name }}</option>
                            {% endfor %}
                        </select>
                        <select id="footer-posts-sort">
                            <option value="">{{ t('table.title') }}</option>
                            <option value="title-asc">{{ t('table.title') }} A→Z</option>
                            <option value="title-desc">{{ t('table.title') }} Z→A</option>
                        </select>
                        <select id="footer-posts-date">
                            <option value="">{{ t('menus.published') }}</option>
                            <option value="date-desc">{{ t('table.newest_first') }}</option>
                            <option value="date-asc">{{ t('table.oldest_first') }}</option>
                        </select>
                        <span class="selected-counter" id="footer-posts-counter"></span>
                    </div>
                    <table class="content-table" id="footer-posts-table">
                        <thead>
                            <tr>
                                <th class="cb-cell">☑</th>
                                <th>{{ t('table.title') }}</th>
                                <th>{{ t('menus.menu_label') }}</th>
                                <th>{{ t('menus.lang') }}</th>
                                <th>{{ t('menus.published') }}</th>
                            </tr>
                        </thead>
                        <tbody></tbody>
                    </table>
                </div>

                <!-- Custom Links panel -->
                <div id="footer-custom-panel" class="content-panel">
                    <table class="content-table" id="footer-custom-table">
                        <thead>
                            <tr>
                                <th class="cb-cell">🔗</th>
                                <th>{{ t('menus.custom_url_header') }}</th>
                                <th>{{ t('menus.menu_label') }}</th>
                                <th>{{ t('menus.lang') }}</th>
                                <th>{{ t('menus.pick_file') }}</th>
                            </tr>
                        </thead>
                        <tbody>
                            {% for lang in active_languages %}
                            <tr class="row-checked" data-lang="{{ lang.code }}">
                                <td class="cb-cell">🔗</td>
                                <td>
                                    <input type="text" class="label-input custom-links__url"
                                           data-lang="{{ lang.code }}"
                                           placeholder="{{ t('menus.custom_url_placeholder') }}">
                                </td>
                                <td>
                                    <input type="text" class="label-input custom-links__label"
                                           data-lang="{{ lang.code }}"
                                           placeholder="{{ t('menus.custom_label_placeholder') }}">
                                </td>
                                <td><span class="lang-badge">{{ lang.code|upper }}</span></td>
                                <td>
                                    <select class="label-input custom-links__file-picker" data-lang="{{ lang.code }}">
                                        <option value="">📎 {{ t('menus.pick_file') }}</option>
                                        {% for f in files_list %}
                                        <option value="/{{ f.download_slug }}">{{ f.title or f.original_filename or f.filename }}</option>
                                        {% endfor %}
                                    </select>
                                </td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                    <div class="custom-links__bottom">
                        <label class="custom-links__target-label">
                            <input type="checkbox" class="custom-links__target">
                            {{ t('menus.open_new_window') }}
                        </label>
                        <button type="button" class="btn btn-primary"
                                onclick="addCustomLink('footer')">
                            ➕ {{ t('menus.add_to_menu') }}
                        </button>
                    </div>
                </div>
            </div><!-- /.menu-picker -->

        </div><!-- /.menu-builder-layout -->
    </form>
</div><!-- /#footer-form -->
<div class="pagination-footer" id="footer-pages-pagination" style="display:none"></div>
<div class="pagination-footer" id="footer-posts-pagination" style="display:none"></div>

{% endblock %}


{% block extra_js %}
<script>
/* ===================================================================
   MENU BUILDER — combo: HTML5 drag-and-drop + button controls
   No external libraries. Pure vanilla JS.

   Data model:
     Each .menu-item-row in the builder has dataset:
       temp-id  — unique client id ("t-1" new, "srv-42" loaded from DB)
       type     — "page" | "post"
       id       — DB content id (page.id or post.id)
       parent   — temp-id of parent row, or "" for top-level

     Submenus are .menu-submenu divs that follow their parent row
     in the DOM. data-parent-temp links them to the parent row.

   On submit, serializeMenu() walks the DOM and serialises to JSON
   for app.py's admin_menus POST handler (menu_structure field).
=================================================================== */

var _tempCounter = 1000;
function newTempId() { return 't-' + (++_tempCounter); }

/* ── i18n strings (injected from Jinja, used in JS-created DOM) ── */
var _i18n = {
    add_submenu_item: "{{ t('menus.add_submenu_item') | e }}",
    child_item:       "{{ t('menus.child_item') | e }}",
    parent_item:      "{{ t('menus.parent_item') | e }}",
    drag_to_reorder:  "{{ t('menus.drag_to_reorder') | e }}",
    remove_item:      "{{ t('menus.remove_item') | e }}",
    no_menu_items:    "{{ t('menus.no_menu_items') | e }}",
    custom_url_invalid:    "{{ t('menus.custom_url_invalid') | e }}",
    custom_label_required: "{{ t('menus.custom_label_required') | e }}",
    custom_links_empty:    "{{ t('menus.custom_links_empty') | e }}",
    add_to_menu:           "{{ t('menus.add_to_menu') | e }}",
    update_link:           "{{ t('menus.update_link') | e }}",
    edit_link:             "{{ t('menus.edit_link') | e }}",
    max_depth_reached:     "{{ t('menus.max_depth_reached') | e }}"
};

/* Existing custom links from the server — preload into _customLinks store
   so they survive a save round-trip without being re-entered by the user.
   `custom_links_data` is built server-side and passed through tojson, which
   safely escapes any quotes, slashes or script-closing sequences in URLs. */
var _serverCustomLinks = {{ custom_links_data | tojson }};

/* ── HTML escape helper ────────────────────────────────────────── */
function escHtml(s) {
    return String(s)
        .replace(/&/g,'&amp;').replace(/</g,'&lt;')
        .replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}

/* ================================================================
   PICKER STATE — survives pagination; source of truth for checks/labels
================================================================ */
var _pickerI18n = {
    custom_label_placeholder: "{{ t('menus.custom_label_placeholder') | e }}",
    no_pages:          "{{ t('menus.no_pages') | e }}",
    no_posts:          "{{ t('menus.no_posts') | e }}",
    create_first_page: "{{ t('menus.create_first_page') | e }}",
    create_first_post: "{{ t('menus.create_first_post') | e }}",
    url_new_page:      "{{ url_for('admin_pages_new') }}",
    url_new_post:      "{{ url_for('admin_posts_new') }}",
    loading:           "{{ t('common.loading') | e }}",
    prev:              "{{ t('pagination.prev') | e }}",
    next:              "{{ t('pagination.next') | e }}",
    per_page:          "{{ t('pagination.per_page') | e }}",
    per_page_suffix:   "{{ t('pagination.per_page_suffix') | e }}"
};

/* checked[location][type] = { id: true }   — which items are in the builder */
/* labels[location][type]  = { id: "text" } — custom labels typed by user    */
/* checkedGroups[location][type] = { translation_group: true } — checked translation groups (for sibling auto-check across pages) */
var pickerState = {
    checked: { header: { pages: {}, posts: {} }, footer: { pages: {}, posts: {} } },
    labels:  { header: { pages: {}, posts: {} }, footer: { pages: {}, posts: {} } },
    checkedGroups: { header: { pages: {}, posts: {} }, footer: { pages: {}, posts: {} } },
    currentPage: { header: { pages: 1, posts: 1 }, footer: { pages: 1, posts: 1 } }
};

/* ── Initialize from server data ── */
(function() {
    var initChecked = {
        header: {
            pages: {{ checked.header.pages | list | tojson }},
            posts: {{ checked.header.posts | list | tojson }}
        },
        footer: {
            pages: {{ checked.footer.pages | list | tojson }},
            posts: {{ checked.footer.posts | list | tojson }}
        }
    };
    var initLabels = {{ menu_labels | tojson }};
    var initGroups = {{ checked_groups | tojson }};

    ['header', 'footer'].forEach(function(loc) {
        ['pages', 'posts'].forEach(function(type) {
            (initChecked[loc][type] || []).forEach(function(id) {
                pickerState.checked[loc][type][String(id)] = true;
            });
            (initGroups[loc][type] || []).forEach(function(tg) {
                pickerState.checkedGroups[loc][type][tg] = true;
            });
        });
        var locLabels = initLabels[loc] || {};
        for (var key in locLabels) {
            if (!locLabels[key]) continue;
            // key = "page_123" or "post_456"
            var parts = key.split('_');
            var type = parts[0] + 's';   // "pages" or "posts"
            var id   = parts.slice(1).join('_');
            if (pickerState.labels[loc][type]) {
                pickerState.labels[loc][type][id] = locLabels[key];
            }
        }
    });
})();

/* ── Save label from input before leaving page (called on input blur) ── */
function savePickerLabel(location, type, id, input) {
    var val = input.value.trim();
    if (val) {
        pickerState.labels[location][type][String(id)] = val;
    } else {
        delete pickerState.labels[location][type][String(id)];
    }
}

/* ── Debounced search ── */
var _searchTimers = {};
function onPickerSearch(location, type) {
    var key = location + '-' + type;
    clearTimeout(_searchTimers[key]);
    _searchTimers[key] = setTimeout(function() {
        loadPickerPage(location, type, 1);
    }, 300);
}

function onPickerFilter(location, type) {
    loadPickerPage(location, type, 1);
}

/* ================================================================
   LOAD PICKER PAGE — fetch from API and render
================================================================ */
function loadPickerPage(location, type, page) {
    var prefix = location + '-' + type;
    var search = document.getElementById(prefix + '-search');
    var lang   = document.getElementById(prefix + '-lang');
    var sortSel = document.getElementById(prefix + '-sort');
    var dateSel = document.getElementById(prefix + '-date');

    var params = new URLSearchParams();
    params.set('type', type);
    params.set('page', page || 1);
    params.set('per_page', _pickerPerPage[prefix] || 20);
    if (search && search.value.trim()) params.set('search', search.value.trim());
    if (lang && lang.value !== 'all') params.set('lang', lang.value);

    var sortVal = '';
    if (sortSel && sortSel.value) { sortVal = sortSel.value; }
    else if (dateSel && dateSel.value) { sortVal = dateSel.value; }
    if (sortVal) params.set('sort', sortVal);

    var table = document.getElementById(prefix + '-table');
    var tbody = table ? table.querySelector('tbody') : null;
    if (tbody) tbody.innerHTML = '<tr><td colspan="5" class="text-center p-4">' + _pickerI18n.loading + '</td></tr>';

    fetch('/admin/api/menu-picker?' + params.toString())
        .then(function(r) { return r.json(); })
        .then(function(data) {
            pickerState.currentPage[location][type] = data.page;
            renderPickerRows(location, type, data);
            renderPickerPagination(location, type, data);
            updateCounters();
        })
        .catch(function(err) {
            if (tbody) tbody.innerHTML = '<tr><td colspan="5" class="text-center p-4">⚠ ' + escHtml(err.message) + '</td></tr>';
        });
}

/* ── Render table rows ── */
function renderPickerRows(location, type, data) {
    var prefix = location + '-' + type;
    var tbody = document.getElementById(prefix + '-table').querySelector('tbody');
    var singularType = type === 'pages' ? 'page' : 'post';

    if (data.total === 0) {
        var noMsg  = type === 'pages' ? _pickerI18n.no_pages : _pickerI18n.no_posts;
        var newUrl = type === 'pages' ? _pickerI18n.url_new_page : _pickerI18n.url_new_post;
        var newTxt = type === 'pages' ? _pickerI18n.create_first_page : _pickerI18n.create_first_post;
        tbody.innerHTML = '<tr><td colspan="5"><div class="empty-state">'
            + '<p>' + noMsg + '</p>'
            + '<a href="' + newUrl + '">' + newTxt + '</a>'
            + '</div></td></tr>';
        return;
    }

    var html = '';
    data.items.forEach(function(item) {
        var id = String(item.id);
        var tg = item.translation_group || '';
        var isChecked = !!pickerState.checked[location][type][id];

        // Auto-check siblings: if this item's translation_group is already checked, check this row too
        if (!isChecked && tg && pickerState.checkedGroups[location][type][tg]) {
            isChecked = true;
            pickerState.checked[location][type][id] = true;
        }

        // Register translation_group if this item is checked
        if (isChecked && tg) {
            pickerState.checkedGroups[location][type][tg] = true;
        }

        var labelVal  = pickerState.labels[location][type][id] || '';
        var placeholder = _pickerI18n.custom_label_placeholder.replace('{lang}', item.language.toUpperCase());

        html += '<tr data-item-type="' + singularType + '"'
            + ' data-item-id="' + id + '"'
            + ' data-item-label="' + escHtml(item.title) + '"'
            + ' data-item-lang="' + escHtml(item.language.toUpperCase()) + '"'
            + ' data-translation-group="' + escHtml(item.translation_group || '') + '"'
            + (isChecked ? ' class="row-checked"' : '') + '>'
            + '<td class="cb-cell">'
            +   '<input type="checkbox" onchange="toggleRow(this,\'' + location + '\')"'
            +   (isChecked ? ' checked' : '') + '>'
            + '</td>'
            + '<td>'
            +   '<div class="title-cell">' + escHtml(item.title) + '</div>'
            +   '<div class="slug-cell">/' + escHtml(item.slug) + '</div>'
            + '</td>'
            + '<td>'
            +   '<input type="text" class="label-input"'
            +   ' placeholder="' + escHtml(placeholder) + '"'
            +   ' value="' + escHtml(labelVal) + '"'
            +   ' onblur="savePickerLabel(\'' + location + '\',\'' + type + '\',\'' + id + '\',this)">'
            + '</td>'
            + '<td><span class="lang-badge">' + escHtml(item.language.toUpperCase()) + '</span></td>'
            + '<td class="date-cell">' + (item.published_at || '—') + '</td>'
            + '</tr>';
    });
    tbody.innerHTML = html;
}

/* ── Render pagination controls ── */
function renderPickerPagination(location, type, data) {
    var prefix = location + '-' + type;
    var container = document.getElementById(prefix + '-pagination');
    if (!container) return;

    var html = '';

    // Pagination buttons (only if more than 1 page)
    if (data.total_pages > 1) {
        html += '<div class="pagination">';

        if (data.page > 1) {
            html += '<a href="#" onclick="loadPickerPage(\'' + location + '\',\'' + type + '\',' + (data.page - 1) + ');return false">' + _pickerI18n.prev + '</a>';
        }

        var start = Math.max(1, data.page - 2);
        var end   = Math.min(data.total_pages, data.page + 2);

        if (start > 1) {
            html += '<a href="#" onclick="loadPickerPage(\'' + location + '\',\'' + type + '\',1);return false">1</a>';
            if (start > 2) html += '<span class="pagination-ellipsis">…</span>';
        }

        for (var i = start; i <= end; i++) {
            if (i === data.page) {
                html += '<span class="current">' + i + '</span>';
            } else {
                html += '<a href="#" onclick="loadPickerPage(\'' + location + '\',\'' + type + '\',' + i + ');return false">' + i + '</a>';
            }
        }

        if (end < data.total_pages) {
            if (end < data.total_pages - 1) html += '<span class="pagination-ellipsis">…</span>';
            html += '<a href="#" onclick="loadPickerPage(\'' + location + '\',\'' + type + '\',' + data.total_pages + ');return false">' + data.total_pages + '</a>';
        }

        if (data.page < data.total_pages) {
            html += '<a href="#" onclick="loadPickerPage(\'' + location + '\',\'' + type + '\',' + (data.page + 1) + ');return false">' + _pickerI18n.next + '</a>';
        }

        html += '</div>';
    }

    // Per-page selector (always visible)
    html += '<div class="per-page-selector">'
        + _pickerI18n.per_page + ' '
        + '<select onchange="onPickerPerPage(\'' + location + '\',\'' + type + '\',this.value)">'
        + '<option value="20"' + (data.per_page === 20 ? ' selected' : '') + '>20</option>'
        + '<option value="50"' + (data.per_page === 50 ? ' selected' : '') + '>50</option>'
        + '<option value="100"' + (data.per_page === 100 ? ' selected' : '') + '>100</option>'
        + '</select>'
        + ' ' + _pickerI18n.per_page_suffix
        + '</div>';

    container.innerHTML = html;
}

/* ── Per-page change handler ── */
var _pickerPerPage = {};
function onPickerPerPage(location, type, val) {
    _pickerPerPage[location + '-' + type] = parseInt(val, 10);
    loadPickerPage(location, type, 1);
}

/* ================================================================
   LOCATION / CONTENT TABS
================================================================ */
var _activeLocation = 'header';
var _activeContentTab = { header: 'pages', footer: 'pages' };

function _updatePaginationVisibility() {
    ['header', 'footer'].forEach(function(loc) {
        ['pages', 'posts'].forEach(function(type) {
            var el = document.getElementById(loc + '-' + type + '-pagination');
            if (el) el.style.display = (loc === _activeLocation && type === _activeContentTab[loc]) ? '' : 'none';
        });
    });
}

function switchLocationTab(location, e) {
    _activeLocation = location;
    document.querySelectorAll('.menu-tab').forEach(function(t) { t.classList.remove('active'); });
    var btn = (e && e.target && e.target.classList.contains('menu-tab'))
        ? e.target
        : document.querySelector('.menu-tab[data-loc="' + location + '"]');
    if (btn) btn.classList.add('active');
    document.getElementById('header-form').style.display = location === 'header' ? 'block' : 'none';
    document.getElementById('footer-form').style.display = location === 'footer' ? 'block' : 'none';
    _updatePaginationVisibility();
}

window.saveActiveMenu = function() {
    serializeMenu(_activeLocation);
    try {
        sessionStorage.setItem('menuActiveView', JSON.stringify({
            location: _activeLocation,
            tabs: _activeContentTab
        }));
    } catch (err) {}
    document.getElementById(_activeLocation + '-menu-form').submit();
};

function switchContentTab(location, type, e) {
    _activeContentTab[location] = type;
    var form = document.getElementById(location + '-form');
    form.querySelectorAll('.content-tab').forEach(function(t) { t.classList.remove('active'); });
    var btn = (e && e.target && e.target.classList.contains('content-tab'))
        ? e.target
        : form.querySelector('.content-tab[data-tab="' + type + '"]');
    if (btn) btn.classList.add('active');
    form.querySelectorAll('.content-panel').forEach(function(p) { p.classList.remove('active'); });
    var panel = document.getElementById(location + '-' + type + '-panel');
    if (panel) panel.classList.add('active');
    _updatePaginationVisibility();
}

/* ================================================================
   CHECKBOX → BUILDER SYNC
================================================================ */
function toggleRow(checkbox, location) {
    var row = checkbox.closest('tr');
    var type = row.dataset.itemType + 's';   // 'page' → 'pages'
    var id   = row.dataset.itemId;
    var tg   = row.dataset.translationGroup || '';

    if (checkbox.checked) {
        // ── Check this row ──
        row.classList.add('row-checked');
        pickerState.checked[location][type][id] = true;

        // Add ONE builder item (only for the clicked row)
        addItemToBuilder(location, {
            tempId: newTempId(),
            type:   row.dataset.itemType,
            id:     id,
            label:  row.dataset.itemLabel,
            lang:   row.dataset.itemLang,
            tg:     tg,
            parent: ''
        });

        // ── Auto-check visible translation siblings ──
        if (tg) {
            pickerState.checkedGroups[location][type][tg] = true;
            var table = row.closest('table');
            if (table) {
                table.querySelectorAll('tbody tr').forEach(function(siblingRow) {
                    if (siblingRow === row) return;
                    if (siblingRow.dataset.translationGroup !== tg) return;
                    if (siblingRow.dataset.itemType + 's' !== type) return;
                    var sibId = siblingRow.dataset.itemId;
                    if (!pickerState.checked[location][type][sibId]) {
                        pickerState.checked[location][type][sibId] = true;
                        siblingRow.classList.add('row-checked');
                        var cb = siblingRow.querySelector('input[type="checkbox"]');
                        if (cb) cb.checked = true;
                    }
                });
            }
        }
    } else {
        // ── Uncheck this row ──
        row.classList.remove('row-checked');
        delete pickerState.checked[location][type][id];
        delete pickerState.labels[location][type][id];
        var lbl = row.querySelector('.label-input');
        if (lbl) lbl.value = '';
        removeFromBuilderById(location, row.dataset.itemType, id);

        // ── Auto-uncheck visible translation siblings ──
        if (tg) {
            delete pickerState.checkedGroups[location][type][tg];
            var table = row.closest('table');
            if (table) {
                table.querySelectorAll('tbody tr').forEach(function(siblingRow) {
                    if (siblingRow === row) return;
                    if (siblingRow.dataset.translationGroup !== tg) return;
                    if (siblingRow.dataset.itemType + 's' !== type) return;
                    var sibId = siblingRow.dataset.itemId;
                    delete pickerState.checked[location][type][sibId];
                    delete pickerState.labels[location][type][sibId];
                    siblingRow.classList.remove('row-checked');
                    var cb = siblingRow.querySelector('input[type="checkbox"]');
                    if (cb) cb.checked = false;
                    var sibLbl = siblingRow.querySelector('.label-input');
                    if (sibLbl) sibLbl.value = '';
                    // Remove sibling from builder too (in case it was added separately)
                    removeFromBuilderById(location, siblingRow.dataset.itemType, sibId);
                });
            }
        }
    }
    updateCounters();
}

/* ================================================================
   BUILDER — ADD / REMOVE ITEMS
================================================================ */
/* ================================================================
   CUSTOM LINKS — per-language URL + label, optional target
   ================================================================ */
// In-memory store of custom links being created in the form.
// Keyed by tempId. Persisted into hidden inputs at serialize time.
// Existing custom items loaded from server are stored here at init.
var _customLinks = { header: {}, footer: {} };

// File picker → fill URL field for the same language
document.addEventListener('change', function(e) {
    if (e.target.classList && e.target.classList.contains('custom-links__file-picker')) {
        if (!e.target.value) return;
        var lang = e.target.dataset.lang;
        // find sibling URL input in same lang-row
        var row = e.target.closest('.custom-links__lang-row');
        if (!row) return;
        var urlInput = row.querySelector('.custom-links__url');
        if (urlInput) urlInput.value = e.target.value;
        // reset picker so user can pick again
        e.target.value = '';
    }
});

/* Tracks which custom item is currently being edited (per location).
   null = creating new; tempId = updating existing. */
var _editingCustomTid = { header: null, footer: null };

function addCustomLink(location) {
    var panel = document.getElementById(location + '-custom-panel');
    var urlInputs = panel.querySelectorAll('.custom-links__url');
    var labelInputs = panel.querySelectorAll('.custom-links__label');
    var targetCb = panel.querySelector('.custom-links__target');

    // Whitelisted URL schemes — block javascript:/data:/etc on the client too.
    // The server enforces this whitelist independently in app.py.
    var allowed = /^(https?:\/\/|mailto:|tel:|\/)/i;

    var urls = {};
    var labels = {};
    var defaultLabel = '';
    urlInputs.forEach(function(u) {
        var lang = u.dataset.lang;
        var urlVal = (u.value || '').trim();
        if (!urlVal) return;
        if (!allowed.test(urlVal)) {
            AdminDialog.alert(_i18n.custom_url_invalid + ' (' + lang.toUpperCase() + ')');
            return;
        }
        var labelEl = panel.querySelector('.custom-links__label[data-lang="' + lang + '"]');
        var labelVal = labelEl ? (labelEl.value || '').trim() : '';
        if (!labelVal) {
            AdminDialog.alert(_i18n.custom_label_required + ' (' + lang.toUpperCase() + ')');
            return;
        }
        urls[lang] = urlVal;
        labels[lang] = labelVal;
        if (!defaultLabel) defaultLabel = labelVal;
    });

    if (Object.keys(urls).length === 0) {
        AdminDialog.alert(_i18n.custom_links_empty);
        return;
    }

    var editingTid = _editingCustomTid[location];
    var target = targetCb && targetCb.checked ? '_blank' : '_self';

    if (editingTid) {
        // Update mode: replace data in store and refresh the row label
        _customLinks[location][editingTid] = { urls: urls, labels: labels, target: target };
        var list = document.getElementById(location + '-builder-list');
        var existingRow = list.querySelector('.menu-item-row[data-temp-id="' + editingTid + '"]');
        if (existingRow) {
            var lblEl = existingRow.querySelector('.menu-item-row__label');
            if (lblEl) lblEl.textContent = defaultLabel;
        }
        exitCustomEditMode(location);
    } else {
        // Create mode: new tempId, new row in builder
        var tempId = newTempId();
        _customLinks[location][tempId] = { urls: urls, labels: labels, target: target };
        addItemToBuilder(location, {
            tempId: tempId,
            type:   'custom',
            id:     tempId,
            label:  defaultLabel,
            lang:   '★',
            tg:     '',
            parent: ''
        });
        // Reset form fields
        urlInputs.forEach(function(u) { u.value = ''; });
        labelInputs.forEach(function(l) { l.value = ''; });
        if (targetCb) targetCb.checked = false;
    }
    showEmptyIfNeeded(location);
    updateCounters();
}

/* Open existing custom link's data in the form for editing.
   Called from the pencil button on a custom item in the builder list. */
function editCustomLink(btn, location) {
    var row = btn.closest('.menu-item-row');
    var tid = row.dataset.tempId;
    var data = _customLinks[location][tid];
    if (!data) return;

    var panel = document.getElementById(location + '-custom-panel');
    panel.querySelectorAll('.custom-links__url').forEach(function(u) {
        u.value = data.urls[u.dataset.lang] || '';
    });
    panel.querySelectorAll('.custom-links__label').forEach(function(l) {
        l.value = data.labels[l.dataset.lang] || '';
    });
    var targetCb = panel.querySelector('.custom-links__target');
    if (targetCb) targetCb.checked = (data.target === '_blank');

    // Switch the bottom button label to "Update"
    _editingCustomTid[location] = tid;
    var btnEl = panel.querySelector('.custom-links__bottom .btn-primary');
    if (btnEl) btnEl.innerHTML = '✏️ ' + _i18n.update_link;

    // Switch to the Custom Links tab + scroll the form into view
    switchContentTab(location, 'custom', null);
    panel.scrollIntoView({ behavior: 'smooth', block: 'start' });
}

function exitCustomEditMode(location) {
    _editingCustomTid[location] = null;
    var panel = document.getElementById(location + '-custom-panel');
    panel.querySelectorAll('.custom-links__url').forEach(function(u) { u.value = ''; });
    panel.querySelectorAll('.custom-links__label').forEach(function(l) { l.value = ''; });
    var targetCb = panel.querySelector('.custom-links__target');
    if (targetCb) targetCb.checked = false;
    var btnEl = panel.querySelector('.custom-links__bottom .btn-primary');
    if (btnEl) btnEl.innerHTML = '➕ ' + _i18n.add_to_menu;
}

function addItemToBuilder(location, item) {
    var list  = document.getElementById(location + '-builder-list');
    var empty = document.getElementById(location + '-builder-empty');
    if (empty) empty.remove();

    var isFooter = (location === 'footer');
    var row = document.createElement('div');
    row.className   = 'menu-item-row';
    row.draggable   = true;
    row.dataset.tempId = item.tempId;
    row.dataset.type   = item.type;
    row.dataset.id     = item.id;
    row.dataset.parent = item.parent || '';
    row.dataset.translationGroup = item.tg || '';
    row.addEventListener('dragstart', onItemDragStart);
    row.addEventListener('dragend',   onItemDragEnd);

    var nestBtn = isFooter ? '' :
        '<button type="button" class="menu-item-row__add-child menu-item-row__nest is-hidden" '
        + 'onclick="nestItem(this,\'' + location + '\')" '
        + 'title="' + _i18n.add_submenu_item + '">⤵ ' + _i18n.child_item + '</button>'
        + '<button type="button" class="menu-item-row__add-child menu-item-row__unnest is-hidden" '
        + 'onclick="unnestItem(this,\'' + location + '\')" '
        + 'title="' + _i18n.parent_item + '">⤴ ' + _i18n.parent_item + '</button>';

    // Custom links get an additional edit (pencil) button — pages/posts don't,
    // because their content is edited in their own admin pages, not here.
    var editBtn = (item.type === 'custom') ?
        '<button type="button" class="menu-item-row__edit" '
        + 'onclick="editCustomLink(this,\'' + location + '\')" '
        + 'title="' + _i18n.edit_link + '">✏️</button>' : '';

    row.innerHTML =
        '<span class="menu-item-row__handle" title="' + _i18n.drag_to_reorder + '">⠿</span>'
        + '<span class="menu-item-row__label">' + escHtml(item.label) + '</span>'
        + '<span class="menu-item-row__lang">'  + escHtml(item.lang)  + '</span>'
        + '<div class="menu-item-row__actions">'
        +   nestBtn
        +   editBtn
        +   '<button type="button" class="menu-item-row__remove" '
        +     'onclick="removeItem(this,\'' + location + '\')" '
        +     'title="' + _i18n.remove_item + '">✕</button>'
        + '</div>';

    list.appendChild(row);
    refreshAllRowControls(location);
}

function removeItem(btn, location) {
    var row  = btn.closest('.menu-item-row');
    var tid  = row.dataset.tempId;
    var tg   = row.dataset.translationGroup || '';
    var type = row.dataset.type + 's';  // 'page' → 'pages'
    var list = document.getElementById(location + '-builder-list');

    // For custom links, also drop their entry in _customLinks so they
    // don't get re-injected as hidden inputs on the next save. The key
    // there is the temp_id (which equals data-id for custom items).
    if (row.dataset.type === 'custom' && _customLinks[location]) {
        delete _customLinks[location][row.dataset.id];
    }

    // Remove child submenu and uncheck its items in the table
    var sub = list.querySelector('.menu-submenu[data-parent-temp="' + tid + '"]');
    if (sub) {
        sub.querySelectorAll('.menu-item-row').forEach(function(c) {
            uncheckTableRow(location, c.dataset.type, c.dataset.id);
            if (c.dataset.type === 'custom' && _customLinks[location]) {
                delete _customLinks[location][c.dataset.id];
            }
        });
        sub.remove();
    }

    uncheckTableRow(location, row.dataset.type, row.dataset.id);
    row.remove();

    // Clear translation group and uncheck all visible siblings in the picker table
    if (tg) {
        delete pickerState.checkedGroups[location][type][tg];
        ['header', 'footer'].forEach(function(loc) {
            if (loc !== location) return;
            ['pages', 'posts'].forEach(function(tp) {
                var table = document.getElementById(loc + '-' + tp + '-table');
                if (!table) return;
                table.querySelectorAll('tbody tr').forEach(function(siblingRow) {
                    if (siblingRow.dataset.translationGroup !== tg) return;
                    var sibId = siblingRow.dataset.itemId;
                    delete pickerState.checked[location][type][sibId];
                    delete pickerState.labels[location][type][sibId];
                    siblingRow.classList.remove('row-checked');
                    var cb = siblingRow.querySelector('input[type="checkbox"]');
                    if (cb) cb.checked = false;
                    var sibLbl = siblingRow.querySelector('.label-input');
                    if (sibLbl) sibLbl.value = '';
                });
            });
        });
    }

    showEmptyIfNeeded(location);
    updateCounters();
    refreshAllRowControls(location);
}

function removeFromBuilderById(location, type, id) {
    var list = document.getElementById(location + '-builder-list');
    // Top-level
    list.querySelectorAll(':scope > .menu-item-row').forEach(function(row) {
        if (row.dataset.type === type && row.dataset.id === String(id)) {
            var tid = row.dataset.tempId;
            var sub = list.querySelector('.menu-submenu[data-parent-temp="' + tid + '"]');
            if (sub) sub.remove();
            row.remove();
        }
    });
    // Inside submenus — remove the row's OWN submenu (grandchildren) too,
    // otherwise an orphaned container survives and corrupts serialization.
    list.querySelectorAll('.menu-submenu .menu-item-row').forEach(function(row) {
        if (row.dataset.type === type && row.dataset.id === String(id)) {
            var sub = row.closest('.menu-submenu');
            var own = _ownSub(row);
            if (own) own.remove();
            row.remove();
            if (sub && !sub.querySelector('.menu-item-row')) sub.remove();
        }
    });
    showEmptyIfNeeded(location);
}

/* ================================================================
   NEST / UNNEST BUTTONS
================================================================ */
var MENU_MAX_DEPTH = {{ config.MENU_MAX_DEPTH }};

/* Depth of a row = number of .menu-submenu ancestors (0 = top level). */
function _rowDepth(row) {
    var d = 0, el = row.parentElement;
    while (el && !el.classList.contains('menu-builder__list')) {
        if (el.classList.contains('menu-submenu')) d++;
        el = el.parentElement;
    }
    return d;
}

/* The row's own submenu container (adjacent sibling), if any. */
function _ownSub(row) {
    var sib = row.nextElementSibling;
    if (sib && sib.classList.contains('menu-submenu')
        && sib.dataset.parentTemp === row.dataset.tempId) return sib;
    return null;
}

/* Height of a row's branch in tiers: 1 = leaf, 2 = has children, 3 = has grandchildren. */
function _branchHeight(row) {
    var sub = _ownSub(row);
    if (!sub) return 1;
    var h = 1;
    sub.querySelectorAll(':scope > .menu-item-row').forEach(function(r) {
        var ch = _branchHeight(r);
        if (1 + ch > h) h = 1 + ch;
    });
    return h;
}

/* Top-level ancestor row of any element inside the builder list. */
function _topAncestorRow(el, list) {
    var cur = el;
    while (cur && cur.parentElement !== list) cur = cur.parentElement;
    if (cur && cur.classList.contains('menu-submenu')) {
        return list.querySelector('.menu-item-row[data-temp-id="' + cur.dataset.parentTemp + '"]');
    }
    return (cur && cur.classList.contains('menu-item-row')) ? cur : null;
}

/* Move a row TOGETHER WITH its submenu container. */
function _moveBranch(row, container, before) {
    var sub = _ownSub(row);
    if (before && before.parentNode === container) {
        container.insertBefore(row, before);
    } else {
        container.appendChild(row);
    }
    if (sub) container.insertBefore(sub, row.nextSibling);
}

/* Show/hide the nest (⤵) and unnest (⤴) buttons to match the row's position. */
function _refreshRowControls(row, location) {
    var nestBtn   = row.querySelector('.menu-item-row__nest');
    var unnestBtn = row.querySelector('.menu-item-row__unnest');
    var depth = _rowDepth(row);
    if (unnestBtn) unnestBtn.classList.toggle('is-hidden', depth === 0 || location === 'footer');
    if (nestBtn) {
        var prev = row.previousElementSibling;
        while (prev && !prev.classList.contains('menu-item-row')) prev = prev.previousElementSibling;
        var can = !!prev && location !== 'footer'
                  && (depth + _branchHeight(row)) <= (MENU_MAX_DEPTH - 1);
        nestBtn.classList.toggle('is-hidden', !can);
        nestBtn.title = can ? _i18n.add_submenu_item : _i18n.max_depth_reached;
    }
}

function refreshAllRowControls(location) {
    var list = document.getElementById(location + '-builder-list');
    if (!list) return;
    list.querySelectorAll('.menu-item-row').forEach(function(r) {
        _refreshRowControls(r, location);
    });
}

/* Nest a row under its closest preceding SIBLING row (same container). */
function nestItem(btn, location) {
    var row  = btn.closest('.menu-item-row');
    var container = row.parentElement;

    var prev = row.previousElementSibling;
    while (prev && !prev.classList.contains('menu-item-row')) prev = prev.previousElementSibling;
    if (!prev) return;
    if ((_rowDepth(row) + _branchHeight(row)) > (MENU_MAX_DEPTH - 1)) return;

    var parentTid = prev.dataset.tempId;
    var sub = _ownSub(prev);
    if (!sub) {
        sub = document.createElement('div');
        sub.className = 'menu-submenu';
        sub.dataset.parentTemp = parentTid;
        container.insertBefore(sub, prev.nextSibling);
    }
    row.dataset.parent = parentTid;
    _moveBranch(row, sub, null);
    _cleanupEmptySubmenus(document.getElementById(location + '-builder-list'));
    refreshAllRowControls(location);
}

/* Pop a row (with its branch) one level up, right after its parent's branch. */
function unnestItem(btn, location) {
    var row = btn.closest('.menu-item-row');
    var sub = row.parentElement;
    if (!sub.classList.contains('menu-submenu')) return;
    var list = document.getElementById(location + '-builder-list');

    var parentTid = sub.dataset.parentTemp;
    var parentRow = list.querySelector('.menu-item-row[data-temp-id="' + parentTid + '"]');
    var outer = sub.parentElement;   // list or an outer submenu

    row.dataset.parent = outer.classList.contains('menu-submenu')
        ? outer.dataset.parentTemp : '';

    var after = parentRow ? (_ownSub(parentRow) || parentRow) : null;
    _moveBranch(row, outer, after ? after.nextElementSibling : null);

    _cleanupEmptySubmenus(list);
    showEmptyIfNeeded(location);
    refreshAllRowControls(location);
}

/* ================================================================
   DRAG AND DROP — HTML5 native
================================================================ */
var _drag = {
    row:      null,   // element being dragged
    location: null
};

function _finishDrag() {
    // Called from BOTH drop and dragend. Browsers may swallow dragend when
    // the dragged node was re-parented inside the drop handler — relying on
    // dragend alone left stale drag state behind ("works once per reload").
    document.querySelectorAll('.menu-item-row.is-dragging').forEach(function(r) {
        r.classList.remove('is-dragging');
    });
    _removeIndicator();
    _drag.row = null;
}

function onItemDragStart(e) {
    _finishDrag();   // clear any leftovers from a swallowed dragend
    _drag.row      = e.currentTarget;
    _drag.location = _drag.row.closest('.menu-builder').id.replace('-builder','');
    _drag.startX   = e.clientX;
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/plain', _drag.row.dataset.tempId);
    var r = _drag.row;
    setTimeout(function() { if (_drag.row === r) r.classList.add('is-dragging'); }, 0);
}

function onItemDragEnd(e) {
    _finishDrag();
}

function onBuilderDragOver(e, location) {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    if (!_drag.row) return;

    var list = document.getElementById(location + '-builder-list');
    var info = _resolveDropTarget(e.clientY, e.clientX, list, location);

    list.querySelectorAll('.menu-item-row.nest-target').forEach(function(r) {
        r.classList.remove('nest-target');
    });

    if (info.mode === 'nest' && info.target) {
        info.target.classList.add('nest-target');
        _removeIndicator();
    } else if (info.mode === 'reorder' && info.container) {
        _placeIndicator(info.container,
            (info.insertBefore && info.insertBefore.parentNode === info.container)
                ? info.insertBefore : null);
    } else {
        _placeIndicator(list, null);
    }
}

function onBuilderDragLeave(e, location) {
    var list = document.getElementById(location + '-builder-list');
    if (!list.contains(e.relatedTarget)) {
        _removeIndicator();
        list.querySelectorAll('.nest-target').forEach(function(r) { r.classList.remove('nest-target'); });
    }
}

function onBuilderDrop(e, location) {
    e.preventDefault();
    _removeIndicator();
    var list = document.getElementById(location + '-builder-list');
    list.querySelectorAll('.nest-target').forEach(function(r) { r.classList.remove('nest-target'); });
    if (!_drag.row) { _finishDrag(); return; }

    var row  = _drag.row;
    var info = _resolveDropTarget(e.clientY, e.clientX, list, location);
    var h    = _branchHeight(row);

    if (info.mode === 'nest' && info.target && info.target !== row
        && !info.target.contains(row) && !(_ownSub(row) && _ownSub(row).contains(info.target))) {
        // ── Nest row (with its branch) under target — depth-guarded ────
        if ((_rowDepth(info.target) + 1 + (h - 1)) > (MENU_MAX_DEPTH - 1)) {
            // Would exceed max depth → plain sibling reorder next to target.
            info = { mode: 'reorder', target: info.target,
                     insertBefore: info.target, container: info.target.parentElement };
        } else {
            var parentTid = info.target.dataset.tempId;
            var sub = _ownSub(info.target);
            if (!sub) {
                sub = document.createElement('div');
                sub.className = 'menu-submenu';
                sub.dataset.parentTemp = parentTid;
                info.target.parentElement.insertBefore(sub, info.target.nextSibling);
            }
            row.dataset.parent = parentTid;
            _moveBranch(row, sub, null);
            _cleanupEmptySubmenus(list);
            showEmptyIfNeeded(location);
            refreshAllRowControls(location);
            _finishDrag();
            return;
        }
    }

    if (info.mode === 'reorder' && info.container) {
        // ── Reorder / move as sibling inside info.container ────────────
        var isSub = info.container.classList.contains('menu-submenu');
        var targetDepth = isSub
            ? _rowDepth(info.container.querySelector('.menu-item-row') || row) : 0;
        if (isSub) {
            // depth of rows inside this container:
            var probe = info.container.closest('.menu-builder__list') ? info.container : null;
            targetDepth = 0; var el = info.container;
            while (el && !el.classList.contains('menu-builder__list')) {
                if (el.classList.contains('menu-submenu')) targetDepth++;
                el = el.parentElement;
            }
        }
        // Depth guard: instead of dead-ending (which makes the builder feel
        // frozen once a tall tree exists), degrade to the nearest LEGAL
        // action — a top-level move right before the hovered branch. A
        // branch is at most MENU_MAX_DEPTH tall, so top level always fits.
        if ((targetDepth + h - 1) > (MENU_MAX_DEPTH - 1)) {
            var anchorTop = _topAncestorRow(info.container, list);
            info = { mode: 'reorder', container: list,
                     insertBefore: anchorTop || null };
            isSub = false;
        }
        // Only self-swallow is illegal (dropping into one's own subtree);
        // moving into an ANCESTOR container is a perfectly normal move.
        if (_ownSub(row) && _ownSub(row).contains(info.container)) { _finishDrag(); return; }

        row.dataset.parent = isSub ? info.container.dataset.parentTemp : '';
        var before = (info.insertBefore && info.insertBefore !== row) ? info.insertBefore : null;
        _moveBranch(row, info.container, before);
    }

    _cleanupEmptySubmenus(list);
    showEmptyIfNeeded(location);
    refreshAllRowControls(location);
    _finishDrag();
}

/* Kept for any external callers: refresh both buttons from current position. */
function _setRowNested(row, location, nested) {
    _refreshRowControls(row, location);
}

/* Drop any submenu containers left without children after a move. */
function _cleanupEmptySubmenus(list) {
    list.querySelectorAll('.menu-submenu').forEach(function(sub) {
        if (!sub.querySelector('.menu-item-row')) sub.remove();
    });
}

/*
  Resolves what should happen at the current cursor position.

  Gesture model (2.3.4, depth-aware):
  - Vertical movement = reorder as a sibling of the hovered row, in the
    hovered row's own container — works at every tier.
  - Horizontal indent RIGHT over any row = nest as that row's child
    (top row → child, child row → grandchild), depth-guarded in the drop.
  - Horizontal indent LEFT while hovering a nested row of your own parent
    chain = pop one level up (same as the ⤴ button).
  Footer menus stay flat: indent is ignored there.

  Returns { mode:'nest', target } or { mode:'reorder', container, insertBefore }.
*/
function _resolveDropTarget(clientY, clientX, list, location) {
    var dragged = _drag.row;

    var hoveredRow = null;
    list.querySelectorAll('.menu-item-row').forEach(function(r) {
        if (r === dragged) return;
        var rect = r.getBoundingClientRect();
        if (clientY >= rect.top && clientY <= rect.bottom) hoveredRow = r;
    });

    // Hovering a row inside the dragged row's OWN branch can't nest or
    // become a sibling there (self-swallow). Fall back to a top-level
    // reorder instead of dead-ending in the drop handler — otherwise a
    // parent with a tall subtree "refuses to move" over its own area.
    if (hoveredRow && dragged) {
        var dSub = _ownSub(dragged);
        if (dSub && dSub.contains(hoveredRow)) hoveredRow = null;
    }

    var NEST_INDENT = 30;
    var startX = (typeof _drag.startX === 'number') ? _drag.startX : clientX;
    var deltaX = clientX - startX;
    var wantsIndent  = deltaX >  NEST_INDENT && location !== 'footer';
    var wantsOutdent = deltaX < -NEST_INDENT;

    if (!hoveredRow) {
        // Below/above all rows → reorder at the top level by Y.
        var ib = null;
        Array.from(list.children).forEach(function(el) {
            if (el === dragged || el.id === 'menu-drop-indicator') return;
            if (!el.classList.contains('menu-item-row')) return;
            var rect = el.getBoundingClientRect();
            if (clientY < rect.top + rect.height / 2 && ib === null) ib = el;
        });
        return { mode: 'reorder', container: list, insertBefore: ib };
    }

    if (wantsIndent) {
        return { mode: 'nest', target: hoveredRow };
    }

    // Outdent (drag LEFT) applies only when there is no meaningful target
    // under the cursor, or the cursor is on the dragged row's own parent.
    // Without this, moving a grandchild toward another (visually left)
    // child always triggered "pop one level" instead of the intended move.
    var draggedParentRow = null;
    if (dragged && _rowDepth(dragged) > 0) {
        draggedParentRow = list.querySelector('.menu-item-row[data-temp-id="'
            + dragged.parentElement.dataset.parentTemp + '"]');
    }
    if (wantsOutdent && _rowDepth(dragged) > 0
        && (!hoveredRow || hoveredRow === draggedParentRow)) {
        // Pop one level: sibling slot right after the parent's branch.
        var sub = dragged.parentElement;
        var outer = sub.parentElement;
        var parentRow = list.querySelector(
            '.menu-item-row[data-temp-id="' + sub.dataset.parentTemp + '"]');
        var after = parentRow ? (_ownSub(parentRow) || parentRow) : null;
        return { mode: 'reorder', container: outer,
                 insertBefore: after ? after.nextElementSibling : null };
    }

    // Plain vertical move → sibling of the hovered row, in ITS container.
    var hr = hoveredRow.getBoundingClientRect();
    var before = (clientY < hr.top + hr.height / 2)
        ? hoveredRow
        : (_ownSub(hoveredRow) || hoveredRow).nextElementSibling;
    return { mode: 'reorder', container: hoveredRow.parentElement,
             insertBefore: before };
}

var _indicatorEl = null;
function _placeIndicator(container, before) {
    _removeIndicator();
    var list = container.closest('.menu-builder__list') || container;
    // The line is positioned relative to the list, so the list must be a
    // positioning context. Set it once (idempotent) without touching the CSS.
    if (getComputedStyle(list).position === 'static') {
        list.style.position = 'relative';
    }

    // Y of the line, relative to the list. offsetTop chains up to the nearest
    // positioned ancestor (the list), so it works for rows inside submenus too.
    var top;
    if (before) {
        top = before.offsetTop;
    } else {
        var kids = container.querySelectorAll(':scope > .menu-item-row');
        if (kids.length) {
            var last = kids[kids.length - 1];
            top = last.offsetTop + last.offsetHeight;
        } else {
            top = container.offsetTop + container.offsetHeight;
        }
    }

    var line = document.createElement('div');
    line.id = 'menu-drop-indicator';
    // Absolute + pointer-events:none → does NOT shift layout and never steals
    // drag events, which is what prevents the flicker during dragover.
    line.style.cssText =
        'position:absolute;left:0;right:0;height:0;top:' + (top - 1) + 'px;'
        + 'border-top:2px solid var(--adm-primary, #818cf8);'
        + 'pointer-events:none;z-index:5;';
    list.appendChild(line);
    _indicatorEl = line;
}
function _removeIndicator() {
    if (_indicatorEl) { _indicatorEl.remove(); _indicatorEl = null; }
}

/* ================================================================
   TABLE HELPERS
================================================================ */
function updateCounters() {
    ['header', 'footer'].forEach(function(loc) {
        ['pages', 'posts'].forEach(function(type) {
            var ctr = document.getElementById(loc + '-' + type + '-counter');
            if (!ctr) return;
            var n = Object.keys(pickerState.checked[loc][type]).length;
            ctr.textContent = n > 0 ? (n + ' {{ t("table.selected") }}') : '';
        });
    });
}

function uncheckTableRow(location, type, id) {
    var pluralType = type + 's';  // 'page' → 'pages'
    // pickerState only tracks pages and posts. Custom links live in
    // _customLinks and have no corresponding picker table — bail early
    // to avoid TypeError on undefined nested objects.
    if (!pickerState.checked[location] || !pickerState.checked[location][pluralType]) {
        updateCounters();
        return;
    }
    delete pickerState.checked[location][pluralType][String(id)];
    delete pickerState.labels[location][pluralType][String(id)];

    // If the row is currently visible in the table, update it
    var prefix = location + '-' + pluralType;
    var table = document.getElementById(prefix + '-table');
    if (table) {
        table.querySelectorAll('tbody tr').forEach(function(row) {
            if (row.dataset.itemId === String(id)) {
                row.classList.remove('row-checked');
                var cb = row.querySelector('input[type="checkbox"]');
                if (cb) cb.checked = false;
                var lbl = row.querySelector('.label-input');
                if (lbl) lbl.value = '';
            }
        });
    }
    updateCounters();
}

function showEmptyIfNeeded(location) {
    var list = document.getElementById(location + '-builder-list');
    if (!list.querySelector('.menu-item-row')) {
        // Guard against duplicates: if an empty placeholder already exists
        // inside the list, don't create another. This matters when a single
        // user action (e.g. unchecking one translation sibling) triggers
        // multiple cascading removals via removeFromBuilderById, each of
        // which calls showEmptyIfNeeded.
        if (list.querySelector('.menu-builder__empty')) return;

        var d = document.createElement('div');
        d.className = 'menu-builder__empty';
        d.id = location + '-builder-empty';
        d.innerHTML = '<p>' + _i18n.no_menu_items + '</p>';
        list.appendChild(d);
    }
}

/* ================================================================
   FORM SERIALIZATION — inject hidden label inputs from pickerState
================================================================ */
function serializeMenu(location) {
    var list   = document.getElementById(location + '-builder-list');
    var hidden = document.getElementById(location + '-menu-structure');
    var form   = document.getElementById(location + '-menu-form');
    var result = [];

    // Depth-agnostic (2.3.4): every row in document order; its parent is
    // the data-parent-temp of the row's enclosing submenu container (or
    // null at the top level). Document order preserves sibling ordering.
    list.querySelectorAll('.menu-item-row').forEach(function(el) {
        var sub = el.parentElement.classList.contains('menu-submenu')
            ? el.parentElement : null;
        result.push({
            temp_id: el.dataset.tempId,
            type:    el.dataset.type,
            id:      el.dataset.id,
            parent:  sub ? sub.dataset.parentTemp : null
        });
    });

    hidden.value = JSON.stringify(result);

    // Inject hidden inputs for custom labels from pickerState
    // (rows on other pages are not in DOM, so we must add them here)
    form.querySelectorAll('input.picker-label-hidden').forEach(function(el) { el.remove(); });
    ['pages', 'posts'].forEach(function(type) {
        var singularType = type === 'pages' ? 'page' : 'post';
        var labels = pickerState.labels[location][type];
        for (var id in labels) {
            if (!labels[id]) continue;
            var inp = document.createElement('input');
            inp.type = 'hidden';
            inp.className = 'picker-label-hidden';
            inp.name = 'label_' + singularType + '_' + id;
            inp.value = labels[id];
            form.appendChild(inp);
        }
    });

    // Inject hidden inputs for custom links — only for tempIds that are
    // actually present in the builder list (user might have removed some
    // before saving).
    form.querySelectorAll('input.custom-link-hidden').forEach(function(el) { el.remove(); });
    var presentTempIds = new Set(result.map(function(r) {
        return r.type === 'custom' ? r.temp_id : null;
    }).filter(Boolean));
    var store = _customLinks[location];
    Object.keys(store).forEach(function(tid) {
        if (!presentTempIds.has(tid)) return;
        var data = store[tid];
        Object.keys(data.urls).forEach(function(lang) {
            ['url', 'label'].forEach(function(field) {
                var v = field === 'url' ? data.urls[lang] : data.labels[lang];
                if (!v) return;
                var inp = document.createElement('input');
                inp.type = 'hidden';
                inp.className = 'custom-link-hidden';
                inp.name = 'custom_' + field + '_' + tid + '_' + lang;
                inp.value = v;
                form.appendChild(inp);
            });
        });
        var tinp = document.createElement('input');
        tinp.type = 'hidden';
        tinp.className = 'custom-link-hidden';
        tinp.name = 'custom_target_' + tid;
        tinp.value = data.target || '_self';
        form.appendChild(tinp);
    });
}

/* ── Attach filter/sort event listeners ── */
function initPickerEvents() {
    ['header', 'footer'].forEach(function(loc) {
        ['pages', 'posts'].forEach(function(type) {
            var prefix = loc + '-' + type;
            var search  = document.getElementById(prefix + '-search');
            var lang    = document.getElementById(prefix + '-lang');
            var sortSel = document.getElementById(prefix + '-sort');
            var dateSel = document.getElementById(prefix + '-date');

            if (search) search.addEventListener('input', function() { onPickerSearch(loc, type); });
            if (lang)   lang.addEventListener('change', function() { onPickerFilter(loc, type); });
            if (sortSel) sortSel.addEventListener('change', function() {
                if (dateSel) dateSel.selectedIndex = 0;
                onPickerFilter(loc, type);
            });
            if (dateSel) dateSel.addEventListener('change', function() {
                if (sortSel) sortSel.selectedIndex = 0;
                onPickerFilter(loc, type);
            });
        });
    });
}

/* ── Init ──────────────────────────────────────────────────────── */
window.addEventListener('DOMContentLoaded', function() {
    initPickerEvents();
    // Load first page of each picker
    ['header', 'footer'].forEach(function(loc) {
        ['pages', 'posts'].forEach(function(type) {
            loadPickerPage(loc, type, 1);
        });
    });
    // Restore custom links from server-rendered DOM rows
    ['header', 'footer'].forEach(function(loc) {
        var src = _serverCustomLinks[loc] || {};
        Object.keys(src).forEach(function(srvTid) {
            _customLinks[loc][srvTid] = src[srvTid];
        });
    });
    updateCounters();
    ['header', 'footer'].forEach(refreshAllRowControls);

    // Return to the menu + content tab the user was on before saving.
    try {
        var saved = JSON.parse(sessionStorage.getItem('menuActiveView') || 'null');
        if (saved) {
            sessionStorage.removeItem('menuActiveView');
            ['header', 'footer'].forEach(function(loc) {
                var tab = saved.tabs && saved.tabs[loc];
                if (tab) switchContentTab(loc, tab, null);
            });
            if (saved.location) switchLocationTab(saved.location, null);
        }
    } catch (err) {}

    // Clicking a builder item focuses the matching content tab. Clicks on the
    // action buttons are ignored, and a drag does not fire a click, so this
    // never interferes with reordering, nesting or the pencil/remove buttons.
    ['header', 'footer'].forEach(function(loc) {
        var list = document.getElementById(loc + '-builder-list');
        if (!list) return;
        list.addEventListener('click', function(e) {
            if (e.target.closest('button')) return;
            var row = e.target.closest('.menu-item-row');
            if (!row) return;
            var t = row.dataset.type;
            var tab = (t === 'custom') ? 'custom' : (t === 'post') ? 'posts' : 'pages';
            switchContentTab(loc, tab, null);
        });
    });
});
</script>

{% endblock %}
