<?php
require_once __DIR__ . '/../../includes/bootstrap.php';
require_login();

$pageTitle = 'Restaurant Menu Setup';

if (!function_exists('h')) {
    function h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('money_fmt')) {
    function money_fmt($v): string { return number_format((float)$v, 2); }
}
if (!function_exists('rest_flash')) {
    function rest_flash($t, $m): void { $_SESSION['rest_flash'][] = ['type' => $t, 'message' => $m]; }
}
if (!function_exists('rest_get_flash')) {
    function rest_get_flash(): array { $x = $_SESSION['rest_flash'] ?? []; unset($_SESSION['rest_flash']); return $x; }
}

function rest_table_exists(PDO $pdo, string $table): bool
{
    static $cache = [];
    if (array_key_exists($table, $cache)) return $cache[$table];
    $s = $pdo->prepare("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = :t");
    $s->execute([':t' => $table]);
    return $cache[$table] = ((int)$s->fetchColumn() > 0);
}

function rest_column_exists(PDO $pdo, string $table, string $column): bool
{
    static $cache = [];
    $key = $table . '.' . $column;
    if (array_key_exists($key, $cache)) return $cache[$key];
    $s = $pdo->prepare("SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = :t AND column_name = :c");
    $s->execute([':t' => $table, ':c' => $column]);
    return $cache[$key] = ((int)$s->fetchColumn() > 0);
}

function rest_add_column_if_missing(PDO $pdo, string $table, string $column, string $ddl): void
{
    if (rest_table_exists($pdo, $table) && !rest_column_exists($pdo, $table, $column)) {
        $pdo->exec($ddl);
    }
}

function rest_utf8_clean($value): string
{
    $value = (string)$value;

    // Remove UTF-8 BOM and common invisible control bytes from CSV/Excel exports.
    $value = preg_replace('/^\xEF\xBB\xBF/', '', $value) ?? $value;
    $value = str_replace(["\0"], '', $value);

    // Excel/Windows CSV files often arrive as Windows-1252. Byte 0x97 is an em dash.
    // Convert invalid UTF-8 safely before sending to MySQL.
    if (function_exists('mb_check_encoding') && !mb_check_encoding($value, 'UTF-8')) {
        if (function_exists('mb_convert_encoding')) {
            $converted = @mb_convert_encoding($value, 'UTF-8', 'Windows-1252');
            if (is_string($converted) && $converted !== '') {
                $value = $converted;
            }
        } else {
            $converted = @iconv('Windows-1252', 'UTF-8//IGNORE', $value);
            if (is_string($converted) && $converted !== '') {
                $value = $converted;
            }
        }
    }

    // Normalize troublesome smart punctuation to safe printable characters.
    $value = str_replace([
        "\xE2\x80\x93", "\xE2\x80\x94", "\xE2\x88\x92", // en dash, em dash, minus
        "\xE2\x80\x98", "\xE2\x80\x99",                    // smart apostrophes
        "\xE2\x80\x9C", "\xE2\x80\x9D",                    // smart quotes
        "\xC2\xA0"                                            // nbsp
    ], ['-', '-', '-', "'", "'", '"', '"', ' '], $value);

    // Strip any remaining invalid bytes.
    $clean = @iconv('UTF-8', 'UTF-8//IGNORE', $value);
    if (is_string($clean)) {
        $value = $clean;
    }

    return trim($value);
}

function rest_set_utf8_connection(PDO $pdo): void
{
    try { $pdo->exec("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"); } catch (Throwable $e) {}
}

function rest_force_menu_tables_utf8(PDO $pdo): void
{
    foreach (['restaurant_menu_categories','restaurant_menu_items','restaurant_menu_modifiers','restaurant_menu_item_modifiers','restaurant_modifier_groups','restaurant_menu_item_modifier_groups'] as $table) {
        try {
            if (rest_table_exists($pdo, $table)) {
                $pdo->exec("ALTER TABLE `$table` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
            }
        } catch (Throwable $e) {
            // Non-fatal: shared hosting may restrict ALTER; import text is still cleaned below.
        }
    }
}

function rest_slugify(string $text): string
{
    $text = strtolower(rest_utf8_clean($text));
    $text = preg_replace('/[^a-z0-9]+/i', '-', $text);
    $text = trim((string)$text, '-');
    return $text !== '' ? $text : 'category';
}

function rest_button_color_value(string $value, string $fallbackText = ''): string
{
    $value = strtolower(trim(rest_utf8_clean($value)));
    $fallbackText = strtolower(trim(rest_utf8_clean($fallbackText)));

    $named = [
        'food' => '#10b981',
        'restaurant' => '#10b981',
        'main' => '#10b981',
        'grill' => '#ef4444',
        'pizza' => '#f97316',
        'burger' => '#f59e0b',
        'snack' => '#84cc16',
        'drinks' => '#3b82f6',
        'drink' => '#3b82f6',
        'bar' => '#2563eb',
        'cocktail' => '#8b5cf6',
        'cocktails' => '#8b5cf6',
        'wine' => '#dc2626',
        'wines' => '#dc2626',
        'beer' => '#f59e0b',
        'beers' => '#f59e0b',
        'hot' => '#92400e',
        'coffee' => '#92400e',
        'tea' => '#92400e',
        'dessert' => '#ec4899',
        'desserts' => '#ec4899',
        'spa' => '#06b6d4',
        'spar' => '#06b6d4',
        'curio' => '#6366f1',
        'special' => '#f43f5e',
        'specials' => '#f43f5e',
        'blue' => '#3b82f6',
        'green' => '#10b981',
        'emerald' => '#10b981',
        'purple' => '#8b5cf6',
        'red' => '#dc2626',
        'orange' => '#f97316',
        'amber' => '#f59e0b',
        'pink' => '#ec4899',
        'teal' => '#14b8a6',
        'cyan' => '#06b6d4',
        'slate' => '#475569',
        'grey' => '#64748b',
        'gray' => '#64748b',
    ];

    if ($value !== '') {
        if (preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $value)) {
            return $value;
        }
        if (isset($named[$value])) {
            return $named[$value];
        }
    }

    foreach ($named as $key => $hex) {
        if ($fallbackText !== '' && strpos($fallbackText, $key) !== false) {
            return $hex;
        }
    }

    return '#334155';
}

function rest_fetch_categories(PDO $pdo): array
{
    $rows = $pdo->query("SELECT * FROM restaurant_menu_categories ORDER BY parent_id IS NOT NULL, parent_id ASC, sort_order ASC, category_name ASC")->fetchAll(PDO::FETCH_ASSOC);
    $byId = [];
    foreach ($rows as $r) {
        $r['children'] = [];
        $byId[(int)$r['id']] = $r;
    }

    foreach ($byId as $id => $r) {
        $pid = (int)($r['parent_id'] ?? 0);
        if ($pid > 0 && isset($byId[$pid])) {
            $byId[$pid]['children'][] = $id;
        }
    }

    $buildPath = function($id) use (&$buildPath, &$byId): array {
        if (!isset($byId[$id])) return [];
        $pid = (int)($byId[$id]['parent_id'] ?? 0);
        $parentPath = $pid > 0 ? $buildPath($pid) : [];
        $parentPath[] = (string)$byId[$id]['category_name'];
        return $parentPath;
    };

    foreach (array_keys($byId) as $id) {
        $pathParts = $buildPath($id);
        $byId[$id]['path_label'] = implode(' > ', $pathParts);
        $byId[$id]['computed_depth'] = max(0, count($pathParts) - 1);
    }

    uasort($byId, function($a, $b) {
        return strcmp((string)$a['path_label'], (string)$b['path_label']);
    });

    return array_values($byId);
}

function rest_render_tree(array $categories, int $parentId = 0): string
{
    $children = array_filter($categories, fn($c) => (int)($c['parent_id'] ?? 0) === $parentId);
    if (!$children) return '';
    $html = '<ul class="menu-tree-list">';
    foreach ($children as $c) {
        $id = (int)$c['id'];
        $role = h((string)($c['printer_role'] ?? ''));
        $active = (int)($c['is_active'] ?? 1) === 1;
        $hasChildren = false;
        foreach ($categories as $x) { if ((int)($x['parent_id'] ?? 0) === $id) { $hasChildren = true; break; } }
        $html .= '<li class="menu-tree-node" data-parent="' . $parentId . '" data-id="' . $id . '" draggable="true">';
        $html .= '<div class="menu-tree-row" data-drop-id="' . $id . '">';
        $html .= '<span class="drag-handle" title="Drag category onto another category to move it"><i class="bi bi-grip-vertical"></i></span>';
        $html .= '<button type="button" class="btn btn-sm btn-light tree-toggle" data-target="tree-children-' . $id . '">' . ($hasChildren ? '<i class="bi bi-chevron-right"></i>' : '<i class="bi bi-dot"></i>') . '</button>';
        $html .= '<button type="button" class="btn btn-sm btn-outline-dark flex-grow-1 text-start select-cat" title="Edit this root/subroot/category" data-id="' . $id . '" data-name="' . h($c['category_name']) . '" data-parent="' . (int)($c['parent_id'] ?? 0) . '" data-role="' . $role . '" data-color="' . h((string)($c['button_color'] ?? '')) . '" data-sort="' . (int)($c['sort_order'] ?? 1) . '" data-active="' . (int)($c['is_active'] ?? 1) . '" data-path="' . h($c['path_label']) . '">' . str_repeat('&nbsp;&nbsp;', (int)($c['computed_depth'] ?? 0)) . '<i class="bi bi-pencil-square me-1"></i>' . h($c['category_name']) . '</button>';
        $html .= '<span class="drop-hint">drop here</span>';
        $html .= '<span class="badge ' . ($active ? 'text-bg-success' : 'text-bg-secondary') . '">' . ($active ? 'Active' : 'Off') . '</span>';
        $html .= '</div>';
        $childrenHtml = rest_render_tree($categories, $id);
        if ($childrenHtml !== '') $html .= '<div class="tree-children" id="tree-children-' . $id . '" style="display:none">' . $childrenHtml . '</div>';
        $html .= '</li>';
    }
    $html .= '</ul>';
    return $html;
}


function rest_csv_clean($value): string
{
    $value = (string)$value;
    $value = str_replace(["\r\n", "\r", "\n"], ' ', $value);
    return trim($value);
}

function rest_csv_download(string $filename, array $headers, array $rows): void
{
    while (ob_get_level() > 0) { @ob_end_clean(); }
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Pragma: no-cache');
    header('Expires: 0');

    $out = fopen('php://output', 'w');
    fputcsv($out, $headers);
    foreach ($rows as $row) {
        $line = [];
        foreach ($headers as $h) {
            $line[] = rest_csv_clean($row[$h] ?? '');
        }
        fputcsv($out, $line);
    }
    fclose($out);
    exit;
}

function rest_category_path_by_id(array $categories): array
{
    $map = [];
    foreach ($categories as $c) {
        $map[(int)$c['id']] = (string)($c['path_label'] ?? $c['path'] ?? $c['category_name'] ?? '');
    }
    return $map;
}

function rest_find_or_create_category_path(PDO $pdo, string $path, string $printerRole = 'kitchen'): int
{
    $parts = array_values(array_filter(array_map('trim', explode('>', str_replace('|', '>', $path)))));
    if (!$parts) {
        throw new RuntimeException('Category path is required for imported items.');
    }

    $parentId = null;
    $parentPath = '';
    $depth = 0;

    foreach ($parts as $name) {
        $stmt = $pdo->prepare("
            SELECT id, path, depth
            FROM restaurant_menu_categories
            WHERE category_name = :name
              AND " . ($parentId ? "parent_id = :parent_id" : "parent_id IS NULL") . "
            LIMIT 1
        ");
        $params = [':name' => $name];
        if ($parentId) $params[':parent_id'] = $parentId;
        $stmt->execute($params);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($row) {
            $parentId = (int)$row['id'];
            $parentPath = trim((string)($row['path'] ?? ''));
            $depth = (int)($row['depth'] ?? $depth);
            continue;
        }

        $pathLabel = $parentPath !== '' ? ($parentPath . ' > ' . $name) : $name;
        $slug = rest_slugify($name);
        $ins = $pdo->prepare("
            INSERT INTO restaurant_menu_categories
            (parent_id, category_name, slug, depth, path, printer_role, sort_order, is_active)
            VALUES
            (:parent_id, :name, :slug, :depth, :path, :role, 1, 1)
        ");
        $ins->execute([
            ':parent_id' => $parentId ?: null,
            ':name' => $name,
            ':slug' => $slug,
            ':depth' => $depth,
            ':path' => $pathLabel,
            ':role' => $printerRole ?: 'kitchen',
        ]);

        $parentId = (int)$pdo->lastInsertId();
        $parentPath = $pathLabel;
        $depth++;
    }

    return (int)$parentId;
}

function rest_refresh_category_paths(PDO $pdo, ?int $parentId = null, string $parentPath = '', int $depth = 0): void
{
    $sql = "SELECT id, category_name FROM restaurant_menu_categories WHERE " . ($parentId ? "parent_id = :parent_id" : "parent_id IS NULL") . " ORDER BY sort_order ASC, category_name ASC, id ASC";
    $stmt = $pdo->prepare($sql);
    $params = [];
    if ($parentId) $params[':parent_id'] = $parentId;
    $stmt->execute($params);

    $sort = 1;
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $id = (int)$row['id'];
        $name = (string)$row['category_name'];
        $path = $parentPath !== '' ? ($parentPath . ' > ' . $name) : $name;
        $slug = rest_slugify($name);
        $pdo->prepare("UPDATE restaurant_menu_categories SET depth=:depth, path=:path, slug=:slug, sort_order=:sort, updated_at=NOW() WHERE id=:id")
            ->execute([':depth' => $depth, ':path' => $path, ':slug' => $slug, ':sort' => $sort++, ':id' => $id]);
        rest_refresh_category_paths($pdo, $id, $path, $depth + 1);
    }
}

function rest_category_descendant_ids(PDO $pdo, int $categoryId): array
{
    $ids = [];
    $queue = [$categoryId];
    while ($queue) {
        $parent = array_shift($queue);
        $stmt = $pdo->prepare("SELECT id FROM restaurant_menu_categories WHERE parent_id = :parent_id");
        $stmt->execute([':parent_id' => $parent]);
        foreach ($stmt->fetchAll(PDO::FETCH_COLUMN) as $childId) {
            $childId = (int)$childId;
            if ($childId > 0 && !in_array($childId, $ids, true)) {
                $ids[] = $childId;
                $queue[] = $childId;
            }
        }
    }
    return $ids;
}

function rest_move_category(PDO $pdo, int $categoryId, int $newParentId): void
{
    if ($categoryId <= 0) throw new RuntimeException('Invalid category selected.');
    if ($categoryId === $newParentId) throw new RuntimeException('A category cannot be moved into itself.');

    $stmt = $pdo->prepare("SELECT id, category_name FROM restaurant_menu_categories WHERE id = :id LIMIT 1");
    $stmt->execute([':id' => $categoryId]);
    if (!$stmt->fetch(PDO::FETCH_ASSOC)) throw new RuntimeException('Category not found.');

    if ($newParentId > 0) {
        $stmt = $pdo->prepare("SELECT id FROM restaurant_menu_categories WHERE id = :id LIMIT 1");
        $stmt->execute([':id' => $newParentId]);
        if (!$stmt->fetch(PDO::FETCH_ASSOC)) throw new RuntimeException('Target parent category not found.');

        $descendants = rest_category_descendant_ids($pdo, $categoryId);
        if (in_array($newParentId, $descendants, true)) {
            throw new RuntimeException('You cannot move a category inside one of its own subcategories.');
        }
    }

    $stmt = $pdo->prepare("SELECT COALESCE(MAX(sort_order),0) + 1 FROM restaurant_menu_categories WHERE " . ($newParentId > 0 ? "parent_id = :parent_id" : "parent_id IS NULL"));
    $params = [];
    if ($newParentId > 0) $params[':parent_id'] = $newParentId;
    $stmt->execute($params);
    $nextSort = max(1, (int)$stmt->fetchColumn());

    $pdo->beginTransaction();
    $pdo->prepare("UPDATE restaurant_menu_categories SET parent_id = :parent_id, sort_order = :sort, updated_at = NOW() WHERE id = :id")
        ->execute([':parent_id' => $newParentId > 0 ? $newParentId : null, ':sort' => $nextSort, ':id' => $categoryId]);
    rest_refresh_category_paths($pdo, null, '', 0);
    $pdo->commit();
}

function rest_bool_import($value, int $default = 1): int
{
    $v = strtolower(trim((string)$value));
    if ($v === '') return $default;
    return in_array($v, ['1','yes','y','true','active','on'], true) ? 1 : 0;
}

function rest_get_csv_header_map(array $header): array
{
    $map = [];
    foreach ($header as $i => $name) {
        $key = strtolower(rest_utf8_clean($name));
        $key = preg_replace('/[^a-z0-9_]+/', '_', $key);
        $map[$key] = $i;
    }
    return $map;
}

function rest_csv_value(array $row, array $map, array $keys, $default = '')
{
    foreach ($keys as $key) {
        if (array_key_exists($key, $map)) {
            return rest_utf8_clean($row[$map[$key]] ?? $default);
        }
    }
    return rest_utf8_clean($default);
}


function rest_count_table_where(PDO $pdo, string $table, string $whereSql, array $params = []): int
{
    if (!rest_table_exists($pdo, $table)) return 0;
    try {
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM `{$table}` WHERE {$whereSql}");
        $stmt->execute($params);
        return (int)$stmt->fetchColumn();
    } catch (Throwable $e) {
        return 0;
    }
}

function rest_menu_item_usage_count(PDO $pdo, int $menuItemId): int
{
    if ($menuItemId <= 0) return 0;
    $count = 0;

    if (rest_table_exists($pdo, 'restaurant_order_items') && rest_column_exists($pdo, 'restaurant_order_items', 'menu_item_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_order_items', 'menu_item_id = :id', [':id' => $menuItemId]);
    }

    if (rest_table_exists($pdo, 'inventory_recipes') && rest_column_exists($pdo, 'inventory_recipes', 'restaurant_menu_item_id')) {
        $count += rest_count_table_where($pdo, 'inventory_recipes', 'restaurant_menu_item_id = :id', [':id' => $menuItemId]);
    }

    return $count;
}

function rest_modifier_usage_count(PDO $pdo, int $modifierId): int
{
    if ($modifierId <= 0) return 0;
    $count = 0;

    if (rest_table_exists($pdo, 'restaurant_menu_item_modifiers') && rest_column_exists($pdo, 'restaurant_menu_item_modifiers', 'modifier_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_menu_item_modifiers', 'modifier_id = :id', [':id' => $modifierId]);
    }

    if (rest_table_exists($pdo, 'restaurant_modifier_group_options') && rest_column_exists($pdo, 'restaurant_modifier_group_options', 'modifier_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_modifier_group_options', 'modifier_id = :id', [':id' => $modifierId]);
    }

    if (rest_table_exists($pdo, 'restaurant_menu_modifiers') && rest_column_exists($pdo, 'restaurant_menu_modifiers', 'parent_modifier_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_menu_modifiers', 'parent_modifier_id = :id', [':id' => $modifierId]);
    }

    $groupId = 0;
    if (rest_table_exists($pdo, 'restaurant_menu_modifiers') && rest_column_exists($pdo, 'restaurant_menu_modifiers', 'modifier_group_id')) {
        try {
            $stmt = $pdo->prepare("SELECT COALESCE(modifier_group_id,0) FROM restaurant_menu_modifiers WHERE id = :id LIMIT 1");
            $stmt->execute([':id' => $modifierId]);
            $groupId = (int)$stmt->fetchColumn();
        } catch (Throwable $e) { $groupId = 0; }
    }

    if ($groupId > 0 && rest_table_exists($pdo, 'restaurant_menu_item_modifier_groups') && rest_column_exists($pdo, 'restaurant_menu_item_modifier_groups', 'modifier_group_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_menu_item_modifier_groups', 'modifier_group_id = :id', [':id' => $groupId]);
    }

    return $count;
}

function rest_modifier_group_usage_count(PDO $pdo, int $groupId): int
{
    if ($groupId <= 0) return 0;
    $count = 0;

    if (rest_table_exists($pdo, 'restaurant_menu_item_modifier_groups') && rest_column_exists($pdo, 'restaurant_menu_item_modifier_groups', 'modifier_group_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_menu_item_modifier_groups', 'modifier_group_id = :id', [':id' => $groupId]);
    }

    if (rest_table_exists($pdo, 'restaurant_modifier_group_options') && rest_column_exists($pdo, 'restaurant_modifier_group_options', 'modifier_group_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_modifier_group_options', 'modifier_group_id = :id', [':id' => $groupId]);
    }

    if (rest_table_exists($pdo, 'restaurant_menu_modifiers') && rest_column_exists($pdo, 'restaurant_menu_modifiers', 'modifier_group_id')) {
        $count += rest_count_table_where($pdo, 'restaurant_menu_modifiers', 'modifier_group_id = :id', [':id' => $groupId]);
    }

    return $count;
}

function rest_delete_unused_menu_item(PDO $pdo, int $menuItemId): void
{
    if ($menuItemId <= 0) throw new RuntimeException('Invalid menu item selected.');
    if (rest_menu_item_usage_count($pdo, $menuItemId) > 0) {
        throw new RuntimeException('This menu item has already been used or linked to a recipe, so it cannot be deleted. Mark it inactive instead.');
    }

    $pdo->beginTransaction();
    if (rest_table_exists($pdo, 'restaurant_menu_item_modifiers')) {
        $pdo->prepare("DELETE FROM restaurant_menu_item_modifiers WHERE menu_item_id = :id")->execute([':id' => $menuItemId]);
    }
    if (rest_table_exists($pdo, 'restaurant_menu_item_modifier_groups')) {
        $pdo->prepare("DELETE FROM restaurant_menu_item_modifier_groups WHERE menu_item_id = :id")->execute([':id' => $menuItemId]);
    }
    $stmt = $pdo->prepare("DELETE FROM restaurant_menu_items WHERE id = :id LIMIT 1");
    $stmt->execute([':id' => $menuItemId]);
    $pdo->commit();
}

function rest_delete_unused_modifier(PDO $pdo, int $modifierId): void
{
    if ($modifierId <= 0) throw new RuntimeException('Invalid modifier selected.');
    if (rest_modifier_usage_count($pdo, $modifierId) > 0) {
        throw new RuntimeException('This modifier is attached to a menu item, child option, or active group. Remove those links first, or mark it inactive.');
    }

    $stmt = $pdo->prepare("DELETE FROM restaurant_menu_modifiers WHERE id = :id LIMIT 1");
    $stmt->execute([':id' => $modifierId]);
}

function rest_delete_unused_modifier_group(PDO $pdo, int $groupId): void
{
    if ($groupId <= 0) throw new RuntimeException('Invalid modifier group selected.');
    if (rest_modifier_group_usage_count($pdo, $groupId) > 0) {
        throw new RuntimeException('This modifier group has options or is attached to a menu item. Delete/remove those first, or mark it inactive.');
    }

    $stmt = $pdo->prepare("DELETE FROM restaurant_modifier_groups WHERE id = :id LIMIT 1");
    $stmt->execute([':id' => $groupId]);
}


$errors = [];

/*
SQL adjustments applied by this file:

ALTER TABLE restaurant_menu_categories
  ADD parent_id INT UNSIGNED NULL,
  ADD depth INT UNSIGNED NOT NULL DEFAULT 0,
  ADD path VARCHAR(500) NULL,
  ADD slug VARCHAR(180) NULL,
  ADD button_color VARCHAR(30) NULL;

ALTER TABLE restaurant_menu_items
  ADD tags VARCHAR(500) NULL,
  ADD button_color VARCHAR(30) NULL,
  ADD is_selectable TINYINT(1) NOT NULL DEFAULT 1;

CREATE TABLE restaurant_menu_item_modifiers (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  menu_item_id INT UNSIGNED NOT NULL,
  modifier_id INT UNSIGNED NOT NULL,
  is_required TINYINT(1) NOT NULL DEFAULT 0,
  max_select INT UNSIGNED NULL,
  sort_order INT NOT NULL DEFAULT 1,
  UNIQUE KEY uq_item_modifier(menu_item_id, modifier_id)
);
*/
try {
    rest_set_utf8_connection($pdo);
    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_menu_categories (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        property_id INT UNSIGNED NULL,
        parent_id INT UNSIGNED NULL,
        category_name VARCHAR(120) NOT NULL,
        slug VARCHAR(180) NULL,
        button_color VARCHAR(30) NULL,
        depth INT UNSIGNED NOT NULL DEFAULT 0,
        path VARCHAR(500) NULL,
        printer_role VARCHAR(60) NULL,
        sort_order INT NOT NULL DEFAULT 1,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        INDEX idx_rest_cat_parent(parent_id),
        INDEX idx_rest_cat_depth(depth),
        INDEX idx_rest_cat_active(is_active)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    rest_add_column_if_missing($pdo, 'restaurant_menu_categories', 'parent_id', "ALTER TABLE restaurant_menu_categories ADD COLUMN parent_id INT UNSIGNED NULL AFTER property_id");
    rest_add_column_if_missing($pdo, 'restaurant_menu_categories', 'slug', "ALTER TABLE restaurant_menu_categories ADD COLUMN slug VARCHAR(180) NULL AFTER category_name");
    rest_add_column_if_missing($pdo, 'restaurant_menu_categories', 'button_color', "ALTER TABLE restaurant_menu_categories ADD COLUMN button_color VARCHAR(30) NULL AFTER slug");
    rest_add_column_if_missing($pdo, 'restaurant_menu_categories', 'depth', "ALTER TABLE restaurant_menu_categories ADD COLUMN depth INT UNSIGNED NOT NULL DEFAULT 0 AFTER slug");
    rest_add_column_if_missing($pdo, 'restaurant_menu_categories', 'path', "ALTER TABLE restaurant_menu_categories ADD COLUMN path VARCHAR(500) NULL AFTER depth");

    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_menu_items (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        property_id INT UNSIGNED NULL,
        category_id INT UNSIGNED NULL,
        inventory_item_id INT UNSIGNED NULL,
        item_name VARCHAR(180) NOT NULL,
        item_code VARCHAR(60) NULL,
        description TEXT NULL,
        price DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        tax_rate DECIMAL(7,4) NOT NULL DEFAULT 0.0000,
        tags VARCHAR(500) NULL,
        button_color VARCHAR(30) NULL,
        is_selectable TINYINT(1) NOT NULL DEFAULT 1,
        printer_role VARCHAR(60) NULL,
        default_printer_id INT UNSIGNED NULL,
        is_food TINYINT(1) NOT NULL DEFAULT 0,
        is_bar TINYINT(1) NOT NULL DEFAULT 0,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        sort_order INT NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        INDEX idx_rest_item_category(category_id),
        INDEX idx_rest_item_active(is_active),
        INDEX idx_rest_item_search(item_name, item_code)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    rest_add_column_if_missing($pdo, 'restaurant_menu_items', 'tags', "ALTER TABLE restaurant_menu_items ADD COLUMN tags VARCHAR(500) NULL AFTER tax_rate");
    rest_add_column_if_missing($pdo, 'restaurant_menu_items', 'button_color', "ALTER TABLE restaurant_menu_items ADD COLUMN button_color VARCHAR(30) NULL AFTER tags");
    rest_add_column_if_missing($pdo, 'restaurant_menu_items', 'is_selectable', "ALTER TABLE restaurant_menu_items ADD COLUMN is_selectable TINYINT(1) NOT NULL DEFAULT 1 AFTER button_color");

    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_menu_modifiers (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        property_id INT UNSIGNED NULL,
        modifier_name VARCHAR(120) NOT NULL,
        price_delta DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX idx_rest_mod_active(is_active)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_menu_item_modifiers (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        menu_item_id INT UNSIGNED NOT NULL,
        modifier_id INT UNSIGNED NOT NULL,
        is_required TINYINT(1) NOT NULL DEFAULT 0,
        max_select INT UNSIGNED NULL,
        sort_order INT NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        UNIQUE KEY uq_rest_item_modifier(menu_item_id, modifier_id),
        INDEX idx_rest_item_mod_item(menu_item_id),
        INDEX idx_rest_item_mod_modifier(modifier_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_modifier_groups (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        property_id INT UNSIGNED NULL,
        group_name VARCHAR(120) NOT NULL,
        group_type ENUM('required','optional','default') NOT NULL DEFAULT 'optional',
        min_select INT UNSIGNED NOT NULL DEFAULT 0,
        max_select INT UNSIGNED NOT NULL DEFAULT 1,
        sort_order INT NOT NULL DEFAULT 1,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        INDEX idx_rest_mod_group_active(is_active)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_menu_item_modifier_groups (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        menu_item_id INT UNSIGNED NOT NULL,
        modifier_group_id INT UNSIGNED NOT NULL,
        sort_order INT NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        UNIQUE KEY uq_rest_item_group(menu_item_id, modifier_group_id),
        INDEX idx_rest_item_group_item(menu_item_id),
        INDEX idx_rest_item_group_group(modifier_group_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    /*
     * New reusable modifier approach:
     * - restaurant_menu_modifiers now stores reusable modifiers/options once.
     * - restaurant_modifier_group_options links any modifier to one or more groups.
     * This lets you create modifiers first, then reuse/link them in Doneness, Sauce,
     * Cocktail Size, Breakfast Add-ons, etc.
     */
    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_modifier_group_options (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        modifier_group_id INT UNSIGNED NOT NULL,
        modifier_id INT UNSIGNED NOT NULL,
        sort_order INT NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        UNIQUE KEY uq_rest_group_modifier(modifier_group_id, modifier_id),
        INDEX idx_rest_group_option_group(modifier_group_id),
        INDEX idx_rest_group_option_modifier(modifier_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    rest_add_column_if_missing($pdo, 'restaurant_menu_modifiers', 'modifier_group_id', "ALTER TABLE restaurant_menu_modifiers ADD COLUMN modifier_group_id INT UNSIGNED NULL AFTER property_id");
    rest_add_column_if_missing($pdo, 'restaurant_menu_modifiers', 'parent_modifier_id', "ALTER TABLE restaurant_menu_modifiers ADD COLUMN parent_modifier_id INT UNSIGNED NULL AFTER modifier_group_id");
    rest_add_column_if_missing($pdo, 'restaurant_menu_modifiers', 'prefix_allowed', "ALTER TABLE restaurant_menu_modifiers ADD COLUMN prefix_allowed TINYINT(1) NOT NULL DEFAULT 1 AFTER price_delta");
    rest_add_column_if_missing($pdo, 'restaurant_menu_modifiers', 'sort_order', "ALTER TABLE restaurant_menu_modifiers ADD COLUMN sort_order INT NOT NULL DEFAULT 1 AFTER prefix_allowed");


    rest_force_menu_tables_utf8($pdo);
} catch (Throwable $e) {
    $errors[] = 'Could not prepare restaurant menu tables: ' . $e->getMessage();
}


if (($_GET['export'] ?? '') === 'template') {
    rest_csv_download(
        'restaurant_menu_import_template.csv',
        ['category_path','category_button_color','item_name','item_code','description','price','tax_rate','printer_role','tags','button_color','is_food','is_bar','is_selectable','is_active','sort_order','modifiers'],
        [[
            'category_path' => 'Food > Drinks > Cocktails',
            'category_button_color' => 'purple',
            'item_name' => 'Classic Mojito',
            'item_code' => 'MOJITO',
            'description' => 'Rum, mint, lime and soda',
            'price' => '8.00',
            'tax_rate' => '0',
            'printer_role' => 'bar',
            'tags' => 'cocktail, mint',
            'button_color' => 'blue',
            'is_food' => '0',
            'is_bar' => '1',
            'is_selectable' => '1',
            'is_active' => '1',
            'sort_order' => '1',
            'modifiers' => 'Extra lime:0; Double shot:3.00'
        ]]
    );
}

if (($_GET['export'] ?? '') === 'items') {
    $categoriesForExport = rest_fetch_categories($pdo);
    $catPath = rest_category_path_by_id($categoriesForExport);

    $stmt = $pdo->query("
        SELECT i.*,
               GROUP_CONCAT(CONCAT(m.modifier_name, ':', FORMAT(m.price_delta, 2)) ORDER BY m.modifier_name SEPARATOR '; ') AS modifiers
        FROM restaurant_menu_items i
        LEFT JOIN restaurant_menu_item_modifiers im ON im.menu_item_id = i.id
        LEFT JOIN restaurant_menu_modifiers m ON m.id = im.modifier_id
        GROUP BY i.id
        ORDER BY i.id
    ");
    $rows = [];
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
        $rows[] = [
            'category_path' => $catPath[(int)($r['category_id'] ?? 0)] ?? '',
            'category_button_color' => '',
            'item_name' => $r['item_name'] ?? '',
            'item_code' => $r['item_code'] ?? '',
            'description' => $r['description'] ?? '',
            'price' => $r['price'] ?? '0.00',
            'tax_rate' => $r['tax_rate'] ?? '0',
            'printer_role' => $r['printer_role'] ?? '',
            'tags' => $r['tags'] ?? '',
            'button_color' => $r['button_color'] ?? '',
            'is_food' => $r['is_food'] ?? '0',
            'is_bar' => $r['is_bar'] ?? '0',
            'is_selectable' => $r['is_selectable'] ?? '1',
            'is_active' => $r['is_active'] ?? '1',
            'sort_order' => $r['sort_order'] ?? '1',
            'modifiers' => $r['modifiers'] ?? '',
        ];
    }
    rest_csv_download(
        'restaurant_menu_items_' . date('Ymd_His') . '.csv',
        ['category_path','category_button_color','item_name','item_code','description','price','tax_rate','printer_role','tags','button_color','is_food','is_bar','is_selectable','is_active','sort_order','modifiers'],
        $rows
    );
}

if (($_GET['export'] ?? '') === 'categories') {
    $rows = [];
    foreach (rest_fetch_categories($pdo) as $c) {
        $rows[] = [
            'id' => $c['id'] ?? '',
            'parent_id' => $c['parent_id'] ?? '',
            'category_path' => $c['path_label'] ?? $c['path'] ?? $c['category_name'] ?? '',
            'category_name' => $c['category_name'] ?? '',
            'button_color' => $c['button_color'] ?? '',
            'depth' => $c['computed_depth'] ?? $c['depth'] ?? 0,
            'printer_role' => $c['printer_role'] ?? '',
            'sort_order' => $c['sort_order'] ?? 1,
            'is_active' => $c['is_active'] ?? 1,
        ];
    }
    rest_csv_download(
        'restaurant_menu_categories_' . date('Ymd_His') . '.csv',
        ['id','parent_id','category_path','category_name','button_color','depth','printer_role','sort_order','is_active'],
        $rows
    );
}

if (($_GET['export'] ?? '') === 'modifiers') {
    $rows = [];
    $stmt = $pdo->query("SELECT modifier_name, price_delta, is_active FROM restaurant_menu_modifiers ORDER BY modifier_name");
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $m) {
        $rows[] = [
            'modifier_name' => $m['modifier_name'] ?? '',
            'price_delta' => $m['price_delta'] ?? '0.00',
            'is_active' => $m['is_active'] ?? '1',
        ];
    }
    rest_csv_download(
        'restaurant_menu_modifiers_' . date('Ymd_His') . '.csv',
        ['modifier_name','price_delta','is_active'],
        $rows
    );
}


if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    try {
        if (function_exists('verify_csrf')) verify_csrf();
        $action = (string)($_POST['action'] ?? '');

        if ($action === 'delink_inventory_item') {
            $id = (int)($_POST['id'] ?? 0);
            if ($id <= 0) {
                throw new RuntimeException('Invalid menu item selected for inventory delinking.');
            }

            $stmt = $pdo->prepare("
                SELECT item_name, inventory_item_id
                FROM restaurant_menu_items
                WHERE id = :id
                LIMIT 1
            ");
            $stmt->execute([':id' => $id]);
            $menuItem = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$menuItem) {
                throw new RuntimeException('Menu item not found.');
            }

            if ((int)($menuItem['inventory_item_id'] ?? 0) <= 0) {
                rest_flash('success', 'The menu item is already not linked to inventory.');
            } else {
                $pdo->prepare("
                    UPDATE restaurant_menu_items
                    SET inventory_item_id = NULL,
                        updated_at = NOW()
                    WHERE id = :id
                ")->execute([':id' => $id]);

                rest_flash(
                    'success',
                    'Inventory item delinked from "' . (string)$menuItem['item_name']
                    . '". The menu item remains active and sellable, but direct linked-item stock deduction will stop until it is linked again.'
                );
            }
        } elseif ($action === 'move_category') {
            $categoryId = (int)($_POST['category_id'] ?? 0);
            $newParentId = (int)($_POST['new_parent_id'] ?? 0);
            rest_move_category($pdo, $categoryId, $newParentId);
            rest_flash('success', 'Category moved successfully. The menu tree and breadcrumb paths were refreshed.');
        } elseif ($action === 'delete_unused_menu_item') {
            $id = (int)($_POST['id'] ?? 0);
            rest_delete_unused_menu_item($pdo, $id);
            rest_flash('success', 'Unused menu item deleted.');
        } elseif ($action === 'delete_unused_modifier') {
            $id = (int)($_POST['id'] ?? 0);
            rest_delete_unused_modifier($pdo, $id);
            rest_flash('success', 'Unused modifier deleted.');
        } elseif ($action === 'delete_unused_modifier_group') {
            $id = (int)($_POST['id'] ?? 0);
            rest_delete_unused_modifier_group($pdo, $id);
            rest_flash('success', 'Unused modifier group deleted.');
        } elseif ($action === 'import_items') {
            if (empty($_FILES['import_file']['tmp_name']) || !is_uploaded_file($_FILES['import_file']['tmp_name'])) {
                throw new RuntimeException('Please choose a CSV file to import.');
            }

            $handle = fopen($_FILES['import_file']['tmp_name'], 'r');
            if (!$handle) throw new RuntimeException('Could not read uploaded CSV file.');

            $header = fgetcsv($handle);
            if (!$header) throw new RuntimeException('CSV file is empty or has no header row.');
            $map = rest_get_csv_header_map($header);

            $required = ['category_path', 'item_name', 'price'];
            foreach ($required as $requiredKey) {
                if (!array_key_exists($requiredKey, $map)) {
                    throw new RuntimeException('Import CSV is missing required column: ' . $requiredKey);
                }
            }

            $mode = strtolower(trim((string)($_POST['import_mode'] ?? 'upsert')));
            if (!in_array($mode, ['insert_only','upsert'], true)) $mode = 'upsert';

            $pdo->beginTransaction();
            $imported = 0;
            $updated = 0;
            $skipped = 0;

            while (($row = fgetcsv($handle)) !== false) {
                $categoryPath = trim((string)rest_csv_value($row, $map, ['category_path','category']));
                $itemName = trim((string)rest_csv_value($row, $map, ['item_name','name']));
                if ($categoryPath === '' || $itemName === '') {
                    $skipped++;
                    continue;
                }

                $printerRole = trim((string)rest_csv_value($row, $map, ['printer_role'], 'kitchen'));
                $categoryButtonColor = trim((string)rest_csv_value($row, $map, ['category_button_color','category_color'], ''));
                $categoryId = rest_find_or_create_category_path($pdo, $categoryPath, $printerRole ?: 'kitchen');
                if ($categoryButtonColor !== '') {
                    $pdo->prepare("UPDATE restaurant_menu_categories SET button_color=:c WHERE id=:id AND (button_color IS NULL OR button_color='')")
                        ->execute([':c' => $categoryButtonColor, ':id' => $categoryId]);
                }

                $itemCode = trim((string)rest_csv_value($row, $map, ['item_code','code']));
                $price = (float)rest_csv_value($row, $map, ['price'], 0);
                $tax = (float)rest_csv_value($row, $map, ['tax_rate','tax'], 0);
                $description = trim((string)rest_csv_value($row, $map, ['description','desc']));
                $tags = trim((string)rest_csv_value($row, $map, ['tags']));
                $buttonColor = trim((string)rest_csv_value($row, $map, ['button_color','color']));
                $isFood = rest_bool_import(rest_csv_value($row, $map, ['is_food','food'], '0'), 0);
                $isBar = rest_bool_import(rest_csv_value($row, $map, ['is_bar','bar'], '0'), 0);
                $isSelectable = rest_bool_import(rest_csv_value($row, $map, ['is_selectable','selectable'], '1'), 1);
                $isActive = rest_bool_import(rest_csv_value($row, $map, ['is_active','active'], '1'), 1);
                $sortOrder = (int)rest_csv_value($row, $map, ['sort_order','sort'], 1);
                $modifiersText = trim((string)rest_csv_value($row, $map, ['modifiers','options']));

                $existingId = 0;
                if ($mode === 'upsert') {
                    if ($itemCode !== '') {
                        $chk = $pdo->prepare("SELECT id FROM restaurant_menu_items WHERE item_code=:code LIMIT 1");
                        $chk->execute([':code' => $itemCode]);
                        $existingId = (int)$chk->fetchColumn();
                    }
                    if ($existingId <= 0) {
                        $chk = $pdo->prepare("SELECT id FROM restaurant_menu_items WHERE category_id=:cat AND item_name=:name LIMIT 1");
                        $chk->execute([':cat' => $categoryId, ':name' => $itemName]);
                        $existingId = (int)$chk->fetchColumn();
                    }
                }

                $params = [
                    ':cat' => $categoryId,
                    ':n' => $itemName,
                    ':code' => $itemCode !== '' ? $itemCode : null,
                    ':d' => $description !== '' ? $description : null,
                    ':p' => $price,
                    ':tax' => $tax,
                    ':tags' => $tags !== '' ? $tags : null,
                    ':button_color' => $buttonColor !== '' ? $buttonColor : null,
                    ':is_selectable' => $isSelectable,
                    ':role' => $printerRole !== '' ? $printerRole : null,
                    ':food' => $isFood,
                    ':bar' => $isBar,
                    ':active' => $isActive,
                    ':sort' => $sortOrder,
                ];

                if ($existingId > 0) {
                    $params[':id'] = $existingId;
                    $pdo->prepare("UPDATE restaurant_menu_items
                        SET category_id=:cat, item_name=:n, item_code=:code, description=:d, price=:p, tax_rate=:tax,
                            tags=:tags, button_color=:button_color, is_selectable=:is_selectable,
                            printer_role=:role, is_food=:food, is_bar=:bar, is_active=:active, sort_order=:sort, updated_at=NOW()
                        WHERE id=:id")->execute($params);
                    $itemId = $existingId;
                    $updated++;
                } else {
                    $pdo->prepare("INSERT INTO restaurant_menu_items
                        (category_id, item_name, item_code, description, price, tax_rate, tags, button_color,
                         is_selectable, printer_role, is_food, is_bar, is_active, sort_order)
                        VALUES
                        (:cat, :n, :code, :d, :p, :tax, :tags, :button_color,
                         :is_selectable, :role, :food, :bar, :active, :sort)")->execute($params);
                    $itemId = (int)$pdo->lastInsertId();
                    $imported++;
                }

                if ($modifiersText !== '') {
                    $pdo->prepare("DELETE FROM restaurant_menu_item_modifiers WHERE menu_item_id=:id")->execute([':id' => $itemId]);
                    $sort = 1;
                    foreach (preg_split('/\s*;\s*/', $modifiersText) as $modChunk) {
                        $modChunk = trim($modChunk);
                        if ($modChunk === '') continue;
                        $parts = array_map('trim', explode(':', $modChunk, 2));
                        $modName = $parts[0] ?? '';
                        $modPrice = isset($parts[1]) ? (float)$parts[1] : 0;
                        if ($modName === '') continue;

                        $m = $pdo->prepare("SELECT id FROM restaurant_menu_modifiers WHERE modifier_name=:name LIMIT 1");
                        $m->execute([':name' => $modName]);
                        $modId = (int)$m->fetchColumn();
                        if ($modId <= 0) {
                            $pdo->prepare("INSERT INTO restaurant_menu_modifiers(modifier_name, price_delta, is_active) VALUES(:name, :price, 1)")
                                ->execute([':name' => $modName, ':price' => $modPrice]);
                            $modId = (int)$pdo->lastInsertId();
                        }
                        $pdo->prepare("INSERT IGNORE INTO restaurant_menu_item_modifiers(menu_item_id, modifier_id, sort_order) VALUES(:item, :mod, :sort)")
                            ->execute([':item' => $itemId, ':mod' => $modId, ':sort' => $sort++]);
                    }
                }
            }

            fclose($handle);
            $pdo->commit();
            rest_flash('success', 'Import completed. Added: ' . $imported . ', Updated: ' . $updated . ', Skipped: ' . $skipped . '.');
        } elseif ($action === 'save_modifier_group') {
            $id = (int)($_POST['id'] ?? 0);
            $name = rest_utf8_clean($_POST['group_name'] ?? '');
            $type = rest_utf8_clean($_POST['group_type'] ?? 'optional');
            if (!in_array($type, ['required','optional','default'], true)) $type = 'optional';
            $min = max(0, (int)($_POST['min_select'] ?? 0));
            $max = max(0, (int)($_POST['max_select'] ?? 1));
            $sort = (int)($_POST['sort_order'] ?? 1);
            $active = (int)($_POST['is_active'] ?? 1);
            if ($name === '') throw new RuntimeException('Modifier group name is required.');
            if ($type === 'required' && $min < 1) $min = 1;
            if ($max > 0 && $min > $max) throw new RuntimeException('Min select cannot be greater than max select.');

            $linkedModifierIds = $_POST['linked_modifier_ids'] ?? [];
            if (!is_array($linkedModifierIds)) $linkedModifierIds = [];

            $pdo->beginTransaction();
            if ($id > 0) {
                $pdo->prepare("UPDATE restaurant_modifier_groups SET group_name=:n, group_type=:t, min_select=:min, max_select=:max, sort_order=:s, is_active=:a, updated_at=NOW() WHERE id=:id")
                    ->execute([':n'=>$name, ':t'=>$type, ':min'=>$min, ':max'=>$max, ':s'=>$sort, ':a'=>$active, ':id'=>$id]);
                $groupId = $id;
                $message = 'Modifier group updated.';
            } else {
                $pdo->prepare("INSERT INTO restaurant_modifier_groups(group_name, group_type, min_select, max_select, sort_order, is_active) VALUES(:n,:t,:min,:max,:s,:a)")
                    ->execute([':n'=>$name, ':t'=>$type, ':min'=>$min, ':max'=>$max, ':s'=>$sort, ':a'=>$active]);
                $groupId = (int)$pdo->lastInsertId();
                $message = 'Modifier group added.';
            }

            /* Replace group links with the selected reusable modifiers. */
            $pdo->prepare("DELETE FROM restaurant_modifier_group_options WHERE modifier_group_id = :gid")->execute([':gid' => $groupId]);
            $insLink = $pdo->prepare("INSERT IGNORE INTO restaurant_modifier_group_options(modifier_group_id, modifier_id, sort_order) VALUES(:gid, :mid, :sort)");
            $linkSort = 1;
            foreach ($linkedModifierIds as $mid) {
                $mid = (int)$mid;
                if ($mid > 0) {
                    $insLink->execute([':gid' => $groupId, ':mid' => $mid, ':sort' => $linkSort++]);
                }
            }
            $pdo->commit();
            rest_flash('success', $message . ' Linked modifiers: ' . max(0, $linkSort - 1) . '.');
        } elseif ($action === 'save_modifier_option') {
            $id = (int)($_POST['id'] ?? 0);
            $groupId = (int)($_POST['modifier_group_id'] ?? 0);
            $parentId = (int)($_POST['parent_modifier_id'] ?? 0);
            $name = rest_utf8_clean($_POST['modifier_name'] ?? '');
            $delta = (float)($_POST['price_delta'] ?? 0);
            $prefixAllowed = (int)($_POST['prefix_allowed'] ?? 1);
            $sort = (int)($_POST['sort_order'] ?? 1);
            $active = (int)($_POST['is_active'] ?? 1);
            if ($name === '') throw new RuntimeException('Modifier name is required.');
            if ($id > 0 && $parentId === $id) throw new RuntimeException('A modifier option cannot be its own parent.');

            if ($id > 0) {
                $pdo->beginTransaction();
                $pdo->prepare("UPDATE restaurant_menu_modifiers SET modifier_group_id=:gid, parent_modifier_id=:pid, modifier_name=:n, price_delta=:d, prefix_allowed=:p, sort_order=:s, is_active=:a WHERE id=:id")
                    ->execute([':gid'=>$groupId>0?$groupId:null, ':pid'=>$parentId>0?$parentId:null, ':n'=>$name, ':d'=>$delta, ':p'=>$prefixAllowed, ':s'=>$sort, ':a'=>$active, ':id'=>$id]);
                $modifierId = $id;
                $msg = 'Modifier updated.';
            } else {
                $pdo->beginTransaction();
                $pdo->prepare("INSERT INTO restaurant_menu_modifiers(modifier_group_id, parent_modifier_id, modifier_name, price_delta, prefix_allowed, sort_order, is_active) VALUES(:gid,:pid,:n,:d,:p,:s,:a)")
                    ->execute([':gid'=>$groupId>0?$groupId:null, ':pid'=>$parentId>0?$parentId:null, ':n'=>$name, ':d'=>$delta, ':p'=>$prefixAllowed, ':s'=>$sort, ':a'=>$active]);
                $modifierId = (int)$pdo->lastInsertId();
                $msg = 'Reusable modifier added.';
            }
            if ($groupId > 0) {
                $pdo->prepare("INSERT IGNORE INTO restaurant_modifier_group_options(modifier_group_id, modifier_id, sort_order) VALUES(:gid, :mid, :sort)")
                    ->execute([':gid' => $groupId, ':mid' => $modifierId, ':sort' => $sort]);
            }
            $pdo->commit();
            rest_flash('success', $msg . ($groupId > 0 ? ' Linked to selected group.' : ' You can now link it to one or more groups.'));
        } elseif ($action === 'save_category') {
            $id = (int)($_POST['id'] ?? 0);
            $name = rest_utf8_clean($_POST['category_name'] ?? '');
            $parentId = (int)($_POST['parent_id'] ?? 0);
            $role = rest_utf8_clean($_POST['printer_role'] ?? '');
            $buttonColor = rest_utf8_clean($_POST['button_color'] ?? '');
            $sort = (int)($_POST['sort_order'] ?? 1);
            $active = (int)($_POST['is_active'] ?? 1);

            if ($name === '') throw new RuntimeException('Category name is required.');
            if ($id > 0 && $parentId === $id) throw new RuntimeException('A category cannot be its own parent.');

            $depth = 0;
            $parentPath = '';
            if ($parentId > 0) {
                $stmt = $pdo->prepare("SELECT depth, path, category_name FROM restaurant_menu_categories WHERE id=:id LIMIT 1");
                $stmt->execute([':id' => $parentId]);
                $parent = $stmt->fetch(PDO::FETCH_ASSOC);
                if (!$parent) throw new RuntimeException('Parent category not found.');
                $depth = (int)($parent['depth'] ?? 0) + 1;
                $parentPath = trim((string)($parent['path'] ?? ''));
                if ($parentPath === '') $parentPath = (string)$parent['category_name'];
            }
            $path = $parentPath !== '' ? ($parentPath . ' > ' . $name) : $name;
            $slug = rest_slugify($name);

            if ($id > 0) {
                $s = $pdo->prepare("UPDATE restaurant_menu_categories
                    SET parent_id=:parent_id, category_name=:n, slug=:slug, depth=:depth, path=:path,
                        button_color=:button_color,
                        printer_role=:r, sort_order=:s, is_active=:a, updated_at=NOW()
                    WHERE id=:id");
                $s->execute([
                    ':parent_id' => $parentId > 0 ? $parentId : null,
                    ':n' => $name,
                    ':slug' => $slug,
                    ':depth' => $depth,
                    ':path' => $path,
                    ':button_color' => $buttonColor ?: null,
                    ':r' => $role ?: null,
                    ':s' => $sort,
                    ':a' => $active,
                    ':id' => $id,
                ]);
                rest_flash('success', 'Category updated.');
            } else {
                $s = $pdo->prepare("INSERT INTO restaurant_menu_categories(parent_id, category_name, slug, depth, path, button_color, printer_role, sort_order, is_active)
                    VALUES(:parent_id, :n, :slug, :depth, :path, :button_color, :r, :s, :a)");
                $s->execute([
                    ':parent_id' => $parentId > 0 ? $parentId : null,
                    ':n' => $name,
                    ':slug' => $slug,
                    ':depth' => $depth,
                    ':path' => $path,
                    ':button_color' => $buttonColor ?: null,
                    ':r' => $role ?: null,
                    ':s' => $sort,
                    ':a' => $active,
                ]);
                rest_flash('success', 'Category added.');
            }
        } elseif ($action === 'save_item') {
            $id = (int)($_POST['id'] ?? 0);
            $name = rest_utf8_clean($_POST['item_name'] ?? '');
            $cat = (int)($_POST['category_id'] ?? 0);
            $price = (float)($_POST['price'] ?? 0);
            $tax = (float)($_POST['tax_rate'] ?? 0);
            $role = rest_utf8_clean($_POST['printer_role'] ?? '');
            $inv = (int)($_POST['inventory_item_id'] ?? 0);
            $tags = rest_utf8_clean($_POST['tags'] ?? '');
            $buttonColor = rest_utf8_clean($_POST['button_color'] ?? '');
            $modifierIds = $_POST['modifier_ids'] ?? [];
            if (!is_array($modifierIds)) $modifierIds = [];
            $modifierGroupIds = $_POST['modifier_group_ids'] ?? [];
            if (!is_array($modifierGroupIds)) $modifierGroupIds = [];

            /*
             * Modifier group prompt order for Planner:
             * The multiple select only tells us which groups are selected; browsers submit
             * selected options in the select's DOM order, not the order the user clicked them.
             * modifier_group_order is maintained by the setup UI and preserves the exact
             * sequence the item should ask for modifiers in the Planner.
             */
            $modifierGroupOrderRaw = trim((string)($_POST['modifier_group_order'] ?? ''));
            $modifierGroupOrder = [];
            if ($modifierGroupOrderRaw !== '') {
                foreach (preg_split('/[,;|\s]+/', $modifierGroupOrderRaw) as $gid) {
                    $gid = (int)$gid;
                    if ($gid > 0) $modifierGroupOrder[] = $gid;
                }
            }
            $selectedGroupMap = [];
            foreach ($modifierGroupIds as $gid) {
                $gid = (int)$gid;
                if ($gid > 0) $selectedGroupMap[$gid] = true;
            }
            $orderedModifierGroupIds = [];
            foreach ($modifierGroupOrder as $gid) {
                if (isset($selectedGroupMap[$gid])) {
                    $orderedModifierGroupIds[] = $gid;
                    unset($selectedGroupMap[$gid]);
                }
            }
            foreach ($selectedGroupMap as $gid => $_unused) {
                $orderedModifierGroupIds[] = (int)$gid;
            }
            $modifierGroupIds = $orderedModifierGroupIds;

            if ($name === '') throw new RuntimeException('Menu item name is required.');
            if ($cat <= 0) throw new RuntimeException('Select category.');
            if ($price < 0) throw new RuntimeException('Price cannot be negative.');

            $params = [
                ':cat' => $cat,
                ':inv' => $inv > 0 ? $inv : null,
                ':n' => $name,
                ':code' => rest_utf8_clean($_POST['item_code'] ?? '') ?: null,
                ':d' => rest_utf8_clean($_POST['description'] ?? '') ?: null,
                ':p' => $price,
                ':tax' => $tax,
                ':tags' => $tags ?: null,
                ':button_color' => $buttonColor ?: null,
                ':is_selectable' => (int)($_POST['is_selectable'] ?? 1),
                ':role' => $role ?: null,
                ':food' => (int)($_POST['is_food'] ?? 0),
                ':bar' => (int)($_POST['is_bar'] ?? 0),
                ':active' => (int)($_POST['is_active'] ?? 1),
                ':sort' => (int)($_POST['sort_order'] ?? 1),
            ];

            $pdo->beginTransaction();
            if ($id > 0) {
                $params[':id'] = $id;
                $pdo->prepare("UPDATE restaurant_menu_items
                    SET category_id=:cat, inventory_item_id=:inv, item_name=:n, item_code=:code, description=:d,
                        price=:p, tax_rate=:tax, tags=:tags, button_color=:button_color, is_selectable=:is_selectable,
                        printer_role=:role, is_food=:food, is_bar=:bar, is_active=:active, sort_order=:sort, updated_at=NOW()
                    WHERE id=:id")->execute($params);
                $itemId = $id;
                rest_flash('success', 'Menu item updated.');
            } else {
                $pdo->prepare("INSERT INTO restaurant_menu_items
                    (category_id, inventory_item_id, item_name, item_code, description, price, tax_rate, tags, button_color,
                     is_selectable, printer_role, is_food, is_bar, is_active, sort_order)
                    VALUES
                    (:cat, :inv, :n, :code, :d, :p, :tax, :tags, :button_color,
                     :is_selectable, :role, :food, :bar, :active, :sort)")->execute($params);
                $itemId = (int)$pdo->lastInsertId();
                rest_flash('success', 'Menu item added.');
            }

            $pdo->prepare("DELETE FROM restaurant_menu_item_modifiers WHERE menu_item_id=:id")->execute([':id' => $itemId]);
            $sort = 1;
            $insMod = $pdo->prepare("INSERT IGNORE INTO restaurant_menu_item_modifiers(menu_item_id, modifier_id, sort_order) VALUES(:item_id, :modifier_id, :sort)");
            foreach ($modifierIds as $modId) {
                $modId = (int)$modId;
                if ($modId > 0) {
                    $insMod->execute([':item_id' => $itemId, ':modifier_id' => $modId, ':sort' => $sort++]);
                }
            }

            $pdo->prepare("DELETE FROM restaurant_menu_item_modifier_groups WHERE menu_item_id=:id")->execute([':id' => $itemId]);
            $sort = 1;
            $insGrp = $pdo->prepare("INSERT IGNORE INTO restaurant_menu_item_modifier_groups(menu_item_id, modifier_group_id, sort_order) VALUES(:item_id, :group_id, :sort)");
            foreach ($modifierGroupIds as $groupId) {
                $groupId = (int)$groupId;
                if ($groupId > 0) {
                    $insGrp->execute([':item_id' => $itemId, ':group_id' => $groupId, ':sort' => $sort++]);
                }
            }
            $pdo->commit();
        } elseif ($action === 'save_modifier') {
            $name = rest_utf8_clean($_POST['modifier_name'] ?? '');
            $delta = (float)($_POST['price_delta'] ?? 0);
            if ($name === '') throw new RuntimeException('Modifier name is required.');
            $pdo->prepare("INSERT INTO restaurant_menu_modifiers(modifier_group_id, modifier_name, price_delta, is_active) VALUES(NULL, :n, :d, 1)")->execute([':n' => $name, ':d' => $delta]);
            rest_flash('success', 'Reusable modifier added. Link it to any modifier group.');
        } elseif ($action === 'save_bulk_modifiers') {
            $bulkText = trim((string)($_POST['bulk_modifiers'] ?? ''));
            if ($bulkText === '') throw new RuntimeException('Enter at least one modifier.');
            $created = 0;
            $skipped = 0;
            $stmtCheck = $pdo->prepare("SELECT id FROM restaurant_menu_modifiers WHERE modifier_name = :n LIMIT 1");
            $stmtIns = $pdo->prepare("INSERT INTO restaurant_menu_modifiers(modifier_group_id, modifier_name, price_delta, is_active) VALUES(NULL, :n, :d, 1)");
            foreach (preg_split('/\r\n|\r|\n|;/', $bulkText) as $line) {
                $line = trim((string)$line);
                if ($line === '') continue;
                $parts = array_map('trim', explode(':', $line, 2));
                $name = rest_utf8_clean($parts[0] ?? '');
                $delta = isset($parts[1]) ? (float)$parts[1] : 0;
                if ($name === '') { $skipped++; continue; }
                $stmtCheck->execute([':n' => $name]);
                if ((int)$stmtCheck->fetchColumn() > 0) { $skipped++; continue; }
                $stmtIns->execute([':n' => $name, ':d' => $delta]);
                $created++;
            }
            rest_flash('success', 'Bulk modifiers created: ' . $created . ($skipped ? ', skipped existing/blank: ' . $skipped : '') . '.');
        }

        header('Location: menu.php');
        exit;
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        rest_flash('danger', $e->getMessage());
        header('Location: menu.php');
        exit;
    }
}

$flashes = rest_get_flash();
$categories = rest_fetch_categories($pdo);

/*
 * Persistent Menu Item filters
 * ----------------------------
 * Once a user applies a search/filter, keep it active through page refreshes,
 * edits, inventory delinking and other POST actions. Filters are cleared only
 * when the user explicitly clicks Reset / Remove Filters.
 */
$menuFilterSessionKey = 'restaurant_menu_item_filters';

if (isset($_GET['reset_menu_filters']) && (string)$_GET['reset_menu_filters'] === '1') {
    unset($_SESSION[$menuFilterSessionKey]);
    header('Location: menu.php');
    exit;
}

$menuFilterKeys = [
    'item_q',
    'item_category_id',
    'item_printer_role',
    'item_status',
    'item_food_bar',
    'item_selectable',
    'item_inventory_link',
    'item_recipe_link',
];

$hasSubmittedMenuFilters = false;
foreach ($menuFilterKeys as $menuFilterKey) {
    if (array_key_exists($menuFilterKey, $_GET)) {
        $hasSubmittedMenuFilters = true;
        break;
    }
}

if ($hasSubmittedMenuFilters) {
    $savedMenuFilters = [];
    foreach ($menuFilterKeys as $menuFilterKey) {
        $value = $_GET[$menuFilterKey] ?? '';
        if (is_array($value)) {
            continue;
        }
        $savedMenuFilters[$menuFilterKey] = trim((string)$value);
    }
    $_SESSION[$menuFilterSessionKey] = $savedMenuFilters;
} elseif (!empty($_SESSION[$menuFilterSessionKey]) && is_array($_SESSION[$menuFilterSessionKey])) {
    foreach ($_SESSION[$menuFilterSessionKey] as $menuFilterKey => $value) {
        if (in_array($menuFilterKey, $menuFilterKeys, true) && !array_key_exists($menuFilterKey, $_GET)) {
            $_GET[$menuFilterKey] = (string)$value;
        }
    }
}

// Menu Items table filters
$itemSearchFilter     = trim((string)($_GET['item_q'] ?? ''));
$itemCategoryFilter   = (int)($_GET['item_category_id'] ?? 0);
$itemRoleFilter       = strtolower(trim((string)($_GET['item_printer_role'] ?? '')));
$itemStatusFilter     = trim((string)($_GET['item_status'] ?? ''));
$itemFoodBarFilter    = strtolower(trim((string)($_GET['item_food_bar'] ?? '')));
$itemSelectableFilter = trim((string)($_GET['item_selectable'] ?? ''));
$itemInventoryFilter  = strtolower(trim((string)($_GET['item_inventory_link'] ?? '')));
$itemRecipeFilter     = strtolower(trim((string)($_GET['item_recipe_link'] ?? '')));

$itemWhere = '1=1';
$itemParams = [];

if ($itemSearchFilter !== '') {
    $itemWhere .= " AND (
        i.item_name LIKE :item_q_name
        OR i.item_code LIKE :item_q_code
        OR i.description LIKE :item_q_desc
        OR i.tags LIKE :item_q_tags
        OR c.category_name LIKE :item_q_cat
        OR c.path LIKE :item_q_path
    )";
    $itemLike = '%' . $itemSearchFilter . '%';
    $itemParams[':item_q_name'] = $itemLike;
    $itemParams[':item_q_code'] = $itemLike;
    $itemParams[':item_q_desc'] = $itemLike;
    $itemParams[':item_q_tags'] = $itemLike;
    $itemParams[':item_q_cat'] = $itemLike;
    $itemParams[':item_q_path'] = $itemLike;
}

if ($itemCategoryFilter > 0) {
    $itemWhere .= " AND i.category_id = :item_category_id";
    $itemParams[':item_category_id'] = $itemCategoryFilter;
}

if ($itemRoleFilter !== '') {
    if ($itemRoleFilter === '__blank__') {
        $itemWhere .= " AND (i.printer_role IS NULL OR i.printer_role = '')";
    } else {
        $itemWhere .= " AND LOWER(COALESCE(i.printer_role,'')) = :item_printer_role";
        $itemParams[':item_printer_role'] = $itemRoleFilter;
    }
}

if ($itemStatusFilter !== '') {
    $itemWhere .= " AND i.is_active = :item_status";
    $itemParams[':item_status'] = (int)$itemStatusFilter;
}

if ($itemFoodBarFilter === 'food') {
    $itemWhere .= " AND COALESCE(i.is_food,0) = 1";
} elseif ($itemFoodBarFilter === 'bar') {
    $itemWhere .= " AND COALESCE(i.is_bar,0) = 1";
} elseif ($itemFoodBarFilter === 'both') {
    $itemWhere .= " AND COALESCE(i.is_food,0) = 1 AND COALESCE(i.is_bar,0) = 1";
} elseif ($itemFoodBarFilter === 'none') {
    $itemWhere .= " AND COALESCE(i.is_food,0) = 0 AND COALESCE(i.is_bar,0) = 0";
}

if ($itemSelectableFilter !== '') {
    $itemWhere .= " AND COALESCE(i.is_selectable,1) = :item_selectable";
    $itemParams[':item_selectable'] = (int)$itemSelectableFilter;
}

if ($itemInventoryFilter === 'linked') {
    $itemWhere .= " AND COALESCE(i.inventory_item_id,0) > 0";
} elseif ($itemInventoryFilter === 'unlinked') {
    $itemWhere .= " AND COALESCE(i.inventory_item_id,0) = 0";
} elseif ($itemInventoryFilter === 'none') {
    $itemWhere .= " AND COALESCE(i.inventory_item_id,0) = 0
                    AND NOT EXISTS (
                        SELECT 1
                        FROM inventory_recipes ir_none
                        WHERE ir_none.restaurant_menu_item_id = i.id
                          AND COALESCE(ir_none.is_active,1) = 1
                    )";
}

if ($itemRecipeFilter === 'linked') {
    $itemWhere .= " AND EXISTS (
        SELECT 1
        FROM inventory_recipes ir_filter
        WHERE ir_filter.restaurant_menu_item_id = i.id
          AND COALESCE(ir_filter.is_active,1) = 1
    )";
} elseif ($itemRecipeFilter === 'unlinked') {
    $itemWhere .= " AND NOT EXISTS (
        SELECT 1
        FROM inventory_recipes ir_filter
        WHERE ir_filter.restaurant_menu_item_id = i.id
          AND COALESCE(ir_filter.is_active,1) = 1
    )";
}

$itemSql = "SELECT
        i.*,
        c.category_name,
        c.path AS category_path,
        inv.item_name AS inventory_item_name,
        inv.item_code AS inventory_item_code,
        (
            SELECT COUNT(*)
            FROM inventory_recipes ir
            WHERE ir.restaurant_menu_item_id = i.id
              AND COALESCE(ir.is_active,1) = 1
        ) AS active_recipe_count,
        (
            SELECT GROUP_CONCAT(
                DISTINCT NULLIF(TRIM(ir2.recipe_name),'')
                ORDER BY ir2.recipe_name
                SEPARATOR ', '
            )
            FROM inventory_recipes ir2
            WHERE ir2.restaurant_menu_item_id = i.id
              AND COALESCE(ir2.is_active,1) = 1
        ) AS active_recipe_names
    FROM restaurant_menu_items i
    LEFT JOIN restaurant_menu_categories c
        ON c.id = i.category_id
    LEFT JOIN inventory_items inv
        ON inv.id = i.inventory_item_id
    WHERE {$itemWhere}
    ORDER BY COALESCE(c.path, c.category_name), i.sort_order, i.item_name";
$itemStmt = $pdo->prepare($itemSql);
$itemStmt->execute($itemParams);
$items = $itemStmt->fetchAll(PDO::FETCH_ASSOC);

$itemTotalCount = 0;
try { $itemTotalCount = (int)$pdo->query("SELECT COUNT(*) FROM restaurant_menu_items")->fetchColumn(); } catch (Throwable $e) { $itemTotalCount = count($items); }

$itemRoleOptions = [];
try {
    $roleRows = $pdo->query("SELECT DISTINCT printer_role FROM restaurant_menu_items WHERE printer_role IS NOT NULL AND printer_role <> '' ORDER BY printer_role")->fetchAll(PDO::FETCH_COLUMN);
    foreach ($roleRows as $roleRow) {
        $roleRow = strtolower(trim((string)$roleRow));
        if ($roleRow !== '') $itemRoleOptions[$roleRow] = ucwords(str_replace('_', ' ', $roleRow));
    }
} catch (Throwable $e) {}
foreach (['kitchen'=>'Kitchen','bar'=>'Bar','master'=>'Master / Receipt','front_office'=>'Front Office'] as $k => $v) {
    if (!isset($itemRoleOptions[$k])) $itemRoleOptions[$k] = $v;
}

$modifierGroups = $pdo->query("SELECT * FROM restaurant_modifier_groups ORDER BY sort_order, group_name")->fetchAll(PDO::FETCH_ASSOC);
$mods = $pdo->query("SELECT m.*, g.group_name, g.group_type FROM restaurant_menu_modifiers m LEFT JOIN restaurant_modifier_groups g ON g.id=m.modifier_group_id ORDER BY COALESCE(g.sort_order,999), COALESCE(g.group_name,'Ungrouped'), COALESCE(m.parent_modifier_id,0), m.sort_order, m.modifier_name")->fetchAll(PDO::FETCH_ASSOC);
$groupModifierLinks = [];
$modifierLinkedGroups = [];
try {
    if (rest_table_exists($pdo, 'restaurant_modifier_group_options')) {
        $linkRows = $pdo->query("SELECT modifier_group_id, modifier_id, sort_order FROM restaurant_modifier_group_options ORDER BY modifier_group_id, sort_order, id")->fetchAll(PDO::FETCH_ASSOC);
        foreach ($linkRows as $lr) {
            $gid = (int)$lr['modifier_group_id'];
            $mid = (int)$lr['modifier_id'];
            $groupModifierLinks[$gid][] = $mid;
            $modifierLinkedGroups[$mid][] = $gid;
        }
    }
} catch (Throwable $e) {}
foreach ($mods as &$m) {
    $mid = (int)$m['id'];
    $linked = $modifierLinkedGroups[$mid] ?? [];
    if (!empty($m['modifier_group_id'])) $linked[] = (int)$m['modifier_group_id'];
    $linked = array_values(array_unique(array_filter($linked)));
    $m['_linked_group_ids'] = $linked;
}
unset($m);
$modsByGroup = [];
foreach ($mods as $m) {
    $linkedGroups = $m['_linked_group_ids'] ?? [];
    if (!$linkedGroups && !empty($m['modifier_group_id'])) $linkedGroups = [(int)$m['modifier_group_id']];
    foreach ($linkedGroups as $gid) {
        $modsByGroup[(int)$gid][] = $m;
    }
}
$itemModifierRows = $pdo->query("SELECT menu_item_id, modifier_id FROM restaurant_menu_item_modifiers")->fetchAll(PDO::FETCH_ASSOC);
$itemModifiers = [];
foreach ($itemModifierRows as $r) {
    $itemModifiers[(int)$r['menu_item_id']][] = (int)$r['modifier_id'];
}
$itemGroupRows = $pdo->query("SELECT menu_item_id, modifier_group_id FROM restaurant_menu_item_modifier_groups")->fetchAll(PDO::FETCH_ASSOC);
$itemModifierGroups = [];
foreach ($itemGroupRows as $r) {
    $itemModifierGroups[(int)$r['menu_item_id']][] = (int)$r['modifier_group_id'];
}
foreach ($items as &$it) {
    $itemId = (int)$it['id'];
    $usageCount = rest_menu_item_usage_count($pdo, $itemId);
    $it['_modifier_ids'] = $itemModifiers[$itemId] ?? [];
    $it['_modifier_group_ids'] = $itemModifierGroups[$itemId] ?? [];
    $it['_usage_count'] = $usageCount;
    $it['_can_delete'] = ($usageCount <= 0);
}
unset($it);
foreach ($mods as &$m) {
    $modifierId = (int)$m['id'];
    $usageCount = rest_modifier_usage_count($pdo, $modifierId);
    $m['_usage_count'] = $usageCount;
    $m['_can_delete'] = ($usageCount <= 0);
}
unset($m);
foreach ($modifierGroups as &$g) {
    $groupId = (int)$g['id'];
    $usageCount = rest_modifier_group_usage_count($pdo, $groupId);
    $g['_usage_count'] = $usageCount;
    $g['_can_delete'] = ($usageCount <= 0);
}
unset($g);
$modsByGroup = [];
foreach ($mods as $m) {
    foreach (($m['_linked_group_ids'] ?? []) as $gid) {
        $modsByGroup[(int)$gid][] = $m;
    }
}

$inventory = [];
try {
    if (rest_table_exists($pdo, 'inventory_items')) {
        $inventory = $pdo->query("SELECT id,item_name,item_code,selling_price FROM inventory_items WHERE is_active=1 ORDER BY item_name")->fetchAll(PDO::FETCH_ASSOC);
    }
} catch (Throwable $e) {}

foreach ($modifierGroups as &$g) {
    $g['_linked_modifier_ids'] = array_values(array_unique(array_map('intval', $groupModifierLinks[(int)$g['id']] ?? [])));
}
unset($g);
$categoryJson = json_encode($categories, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
$itemsJson = json_encode($items, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
$modifierGroupsJson = json_encode($modifierGroups, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
$modsJson = json_encode($mods, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);

require_once __DIR__ . '/../../includes/header.php';
?>
<div class="hero-band compact-restaurant-hero">
    <div class="row align-items-center g-2">
        <div class="col-lg-8">
            <div class="page-eyebrow text-white-50"><i class="bi bi-menu-button-wide"></i> Restaurant POS Setup</div>
            <div class="hero-title mt-1">Restaurant Menu</div>
            <div class="hero-subtitle mt-1">Hierarchical categories, drill-down POS buttons, modifiers, tags and searchable menu items.</div>
        </div>
        <div class="col-lg-4 text-lg-end">
            <a href="?export=template" class="btn btn-outline-light btn-sm"><i class="bi bi-download me-1"></i>Template</a>
            <a href="?export=items" class="btn btn-outline-light btn-sm"><i class="bi bi-file-earmark-excel me-1"></i>Export Items</a>
            <a href="planner.php" class="btn btn-light btn-sm"><i class="bi bi-grid-3x3-gap me-1"></i>Restaurant Planner</a>
        </div>
    </div>
</div>

<datalist id="buttonColorOptions">
    <option value="food"><option value="drinks"><option value="cocktails"><option value="wines"><option value="beers">
    <option value="coffee"><option value="dessert"><option value="spa"><option value="curio"><option value="specials">
    <option value="green"><option value="blue"><option value="purple"><option value="red"><option value="orange">
    <option value="amber"><option value="pink"><option value="teal"><option value="cyan"><option value="slate">
    <option value="#10b981"><option value="#3b82f6"><option value="#8b5cf6"><option value="#dc2626"><option value="#f59e0b">
</datalist>

<?php foreach ($errors as $err): ?><div class="alert alert-danger"><?php echo h($err); ?></div><?php endforeach; ?>
<?php foreach ($flashes as $f): ?><div class="alert alert-<?php echo h($f['type']); ?>"><?php echo h($f['message']); ?></div><?php endforeach; ?>

<div class="menu-workspace-bar">
    <div class="menu-workspace-copy">
        <span class="menu-workspace-kicker">Menu Workspace</span>
        <strong>Build, price and organise the restaurant menu</strong>
        <small>Use the shortcuts to jump directly to the area you need. Less-used setup panels can be collapsed.</small>
    </div>
    <div class="menu-workspace-actions">
        <button type="button" class="workspace-jump active" data-jump-target="menu-items-card">
            <i class="bi bi-list-ul"></i><span>Items</span>
        </button>
        <button type="button" class="workspace-jump" data-jump-target="item-editor-card">
            <i class="bi bi-plus-square"></i><span>New Item</span>
        </button>
        <button type="button" class="workspace-jump" data-jump-target="category-tree-card">
            <i class="bi bi-diagram-3"></i><span>Categories</span>
        </button>
        <button type="button" class="workspace-jump" data-jump-target="modifier-groups-card">
            <i class="bi bi-sliders"></i><span>Modifiers</span>
        </button>
        <button type="button" class="workspace-jump" data-jump-target="pos-preview-card">
            <i class="bi bi-grid-3x3-gap"></i><span>POS Preview</span>
        </button>
        <button type="button" class="workspace-jump" data-jump-target="import-export-card">
            <i class="bi bi-arrow-down-up"></i><span>Import</span>
        </button>
    </div>
</div>

<div class="row g-3 menu-workspace-grid">
    <div class="col-xl-4">
        <div class="card panel-card import-export-card elite-collapsible" id="import-export-card" data-default-collapsed="1">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Import / Export Menu</h5>
                <a class="btn btn-sm btn-outline-primary" href="?export=template"><i class="bi bi-download me-1"></i>Template</a>
            </div>
            <div class="card-body">
                <form method="post" enctype="multipart/form-data" class="mb-3">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="import_items">
                    <label class="form-label">Import CSV Items</label>
                    <input type="file" name="import_file" accept=".csv,text/csv" class="form-control" required>
                    <div class="row g-2 mt-2">
                        <div class="col-7">
                            <select name="import_mode" class="form-select">
                                <option value="upsert">Update existing / add new</option>
                                <option value="insert_only">Insert new only</option>
                            </select>
                        </div>
                        <div class="col-5 d-grid">
                            <button class="btn btn-primary"><i class="bi bi-upload me-1"></i>Import</button>
                        </div>
                    </div>
                    <div class="form-text">
                        Required columns: <strong>category_path, item_name, price</strong>. Example category: Food &gt; Drinks &gt; Cocktails.
                    </div>
                </form>
                <div class="d-flex flex-wrap gap-2">
                    <a class="btn btn-sm btn-outline-success" href="?export=items"><i class="bi bi-file-earmark-spreadsheet me-1"></i>Export Items</a>
                    <a class="btn btn-sm btn-outline-secondary" href="?export=categories"><i class="bi bi-diagram-3 me-1"></i>Export Categories</a>
                    <a class="btn btn-sm btn-outline-secondary" href="?export=modifiers"><i class="bi bi-sliders me-1"></i>Export Modifiers</a>
                </div>
            </div>
        </div>

        <div class="card panel-card mt-3 elite-collapsible" id="category-tree-card" data-default-collapsed="0">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Category Tree</h5>
                <button class="btn btn-sm btn-outline-secondary" type="button" id="newCategoryBtn">New Root</button>
            </div>
            <div class="card-body">
                <div class="root-drop-zone mb-2" id="rootDropZone" data-drop-id="0">
                    <i class="bi bi-arrow-up-square me-1"></i>Drop a category here to make it a root category
                </div>
                <div class="small text-muted mb-2"><i class="bi bi-grip-vertical"></i> Drag a category onto another category to make it a subcategory.</div>
                <div class="menu-tree-box">
                    <?php echo rest_render_tree($categories); ?>
                    <?php if (!$categories): ?><div class="text-muted small">No categories yet.</div><?php endif; ?>
                </div>
                <form method="post" id="dragCategoryForm" class="d-none">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="move_category">
                    <input type="hidden" name="category_id" id="drag_category_id">
                    <input type="hidden" name="new_parent_id" id="drag_new_parent_id">
                </form>
            </div>
        </div>

        <div class="card panel-card mt-3 elite-collapsible" id="category-editor-card" data-default-collapsed="1">
            <div class="card-header"><h5 class="mb-0">Add / Edit Category</h5></div>
            <div class="card-body">
                <form method="post" id="catForm">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="save_category">
                    <input type="hidden" name="id" id="cat_id">
                    <div class="mb-2">
                        <label class="form-label">Parent Category</label>
                        <select name="parent_id" id="cat_parent_id" class="form-select">
                            <option value="0">Root category</option>
                            <?php foreach ($categories as $c): ?>
                                <option value="<?php echo (int)$c['id']; ?>"><?php echo h(str_repeat('— ', (int)($c['computed_depth'] ?? 0)) . ($c['path_label'] ?? $c['category_name'])); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="mb-2">
                        <label class="form-label">Category Name</label>
                        <input name="category_name" id="cat_name" class="form-control" required>
                    </div>
                    <div class="mb-2">
                        <label class="form-label">Breadcrumb Preview</label>
                        <input id="cat_breadcrumb" class="form-control bg-light" readonly>
                    </div>
                    <div class="mb-2">
                        <label class="form-label">Printer Role</label>
                        <select name="printer_role" id="cat_role" class="form-select">
                            <option value="kitchen">Kitchen</option>
                            <option value="bar">Bar</option>
                            <option value="dessert">Dessert / Ice Cream</option>
                            <option value="master">Master</option>
                        </select>
                    </div>
                    <div class="mb-2">
                        <label class="form-label">Category Button Color</label>
                        <div class="input-group">
                            <input name="button_color" id="cat_color" class="form-control" list="buttonColorOptions" placeholder="food / drinks / #10b981">
                            <span class="input-group-text color-preview-dot" id="catColorPreview"></span>
                        </div>
                    </div>
                    <div class="row g-2">
                        <div class="col"><label class="form-label">Sort</label><input type="number" name="sort_order" id="cat_sort" class="form-control" value="1"></div>
                        <div class="col"><label class="form-label">Active</label><select name="is_active" id="cat_active" class="form-select"><option value="1">Yes</option><option value="0">No</option></select></div>
                    </div>
                    <button class="btn btn-primary w-100 mt-3">Save Category</button>
                </form>
            </div>
        </div>

        <div class="card panel-card mt-3 elite-collapsible" id="modifier-groups-card" data-default-collapsed="1">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Modifier Groups</h5>
                <span class="badge text-bg-primary">Required / Optional / Default</span>
            </div>
            <div class="card-body">
                <form method="post" id="modifierGroupForm" class="mb-3">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="save_modifier_group">
                    <input type="hidden" name="id" id="mod_group_id">
                    <div class="mb-2"><label class="form-label">Group Name</label><input name="group_name" id="mod_group_name" class="form-control" placeholder="Doneness, Sauce, Cocktail Size" required></div>
                    <div class="row g-2">
                        <div class="col-6"><label class="form-label">Type</label><select name="group_type" id="mod_group_type" class="form-select"><option value="required">Required</option><option value="optional">Optional</option><option value="default">Default Included</option></select></div>
                        <div class="col-3"><label class="form-label">Min</label><input type="number" min="0" name="min_select" id="mod_group_min" class="form-control" value="0"></div>
                        <div class="col-3"><label class="form-label">Max</label><input type="number" min="0" name="max_select" id="mod_group_max" class="form-control" value="1"><div class="form-text">0 = unlimited</div></div>
                    </div>
                    <div class="row g-2 mt-1">
                        <div class="col-6"><label class="form-label">Sort</label><input type="number" name="sort_order" id="mod_group_sort" class="form-control" value="1"></div>
                        <div class="col-6"><label class="form-label">Active</label><select name="is_active" id="mod_group_active" class="form-select"><option value="1">Yes</option><option value="0">No</option></select></div>
                    </div>
                    <div class="mt-2">
                        <label class="form-label">Link Reusable Modifiers to this Group</label>
                        <select name="linked_modifier_ids[]" id="mod_group_linked_modifiers" class="form-select" multiple size="8">
                            <?php foreach ($mods as $m): ?>
                                <option value="<?php echo (int)$m['id']; ?>">
                                    <?php echo h($m['modifier_name']); ?><?php echo ((float)$m['price_delta'] != 0 ? ' (' . money_fmt($m['price_delta']) . ')' : ''); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">Create modifiers once below, then select the relevant ones here. Hold Ctrl/Shift to select many.</div>
                    </div>
                    <button class="btn btn-outline-primary w-100 mt-2">Save Modifier Group + Links</button>
                    <button type="button" class="btn btn-light w-100 mt-1" id="clearModifierGroupBtn">Clear Group</button>
                </form>

                <div class="modifier-toolbar d-flex gap-2 align-items-center mb-2">
                    <div class="input-group input-group-sm">
                        <span class="input-group-text"><i class="bi bi-search"></i></span>
                        <input type="text" class="form-control" id="modifierGroupSearch" placeholder="Search groups or modifiers...">
                    </div>
                    <button type="button" class="btn btn-sm btn-outline-secondary" id="showAllModifierGroupsBtn">Show All</button>
                </div>

                <div class="modifier-group-list premium-modifier-groups">
                    <?php foreach ($modifierGroups as $g): ?>
                        <?php
                            $gid = (int)$g['id'];
                            $groupMods = $modsByGroup[$gid] ?? [];
                            $topLevelCount = 0;
                            foreach ($groupMods as $gm) { if ((int)($gm['parent_modifier_id'] ?? 0) <= 0) $topLevelCount++; }
                            $previewNames = array_slice(array_map(static fn($m) => (string)($m['modifier_name'] ?? ''), $groupMods), 0, 5);
                            $badgeClass = $g['group_type']==='required' ? 'danger' : ($g['group_type']==='default' ? 'success' : 'secondary');
                        ?>
                        <div class="modifier-group-card edit-mod-group" role="button" tabindex="0"
                            data-group-id="<?php echo $gid; ?>"
                            data-search-text="<?php echo h(strtolower(($g['group_name'] ?? '') . ' ' . implode(' ', $previewNames))); ?>"
                            data-json='<?php echo h(json_encode($g)); ?>'>
                            <div class="mg-main">
                                <div class="mg-icon"><i class="bi bi-sliders2-vertical"></i></div>
                                <div class="mg-copy">
                                    <div class="mg-title"><?php echo h($g['group_name']); ?></div>
                                    <div class="mg-sub">
                                        <span class="badge text-bg-<?php echo $badgeClass; ?>"><?php echo h(ucwords((string)$g['group_type'])); ?></span>
                                        <span><?php echo (int)$g['min_select']; ?>-<?php echo ((int)$g['max_select']===0?'∞':(int)$g['max_select']); ?> selections</span>
                                        <span><?php echo count($groupMods); ?> option(s)</span>
                                    </div>
                                </div>
                            </div>
                            <div class="mg-preview">
                                <?php if ($previewNames): ?>
                                    <?php foreach ($previewNames as $pn): ?><span><?php echo h($pn); ?></span><?php endforeach; ?>
                                    <?php if (count($groupMods) > count($previewNames)): ?><span>+<?php echo count($groupMods) - count($previewNames); ?> more</span><?php endif; ?>
                                <?php else: ?>
                                    <span>No options yet</span>
                                <?php endif; ?>
                            </div>
                            <div class="modifier-delete-row">
                                <?php if (!empty($g['_can_delete'])): ?>
                                    <form method="post" class="d-inline" onsubmit="return confirm('Delete this unused modifier group?');" onclick="event.stopPropagation();">
                                        <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                        <input type="hidden" name="action" value="delete_unused_modifier_group">
                                        <input type="hidden" name="id" value="<?php echo $gid; ?>">
                                        <button type="submit" class="btn btn-sm btn-outline-danger"><i class="bi bi-trash"></i> Delete unused</button>
                                    </form>
                                <?php else: ?>
                                    <span class="small text-muted"><i class="bi bi-lock"></i> In use / has options</span>
                                <?php endif; ?>
                            </div>
                        </div>
                    <?php endforeach; ?>
                    <?php if (!$modifierGroups): ?><div class="text-muted small">No modifier groups yet. Create groups like Doneness, Sauce, Size, Mixer.</div><?php endif; ?>
                </div>

                <div class="modifier-detail-panel mt-3" id="modifierGroupDetailPanel">
                    <div class="modifier-detail-empty">
                        <i class="bi bi-hand-index-thumb"></i>
                        <strong>Click a modifier group above</strong>
                        <span>All options in that group will show here in a clean nested view.</span>
                    </div>
                </div>
            </div>
        </div>

        <div class="card panel-card mt-3 elite-collapsible" id="modifier-options-card" data-default-collapsed="1">
            <div class="card-header"><h5 class="mb-0">Reusable Modifiers / Options</h5></div>
            <div class="card-body">
                <form method="post" id="modifierOptionForm">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="save_modifier_option">
                    <input type="hidden" name="id" id="mod_option_id">
                    <div class="mb-2">
                        <label class="form-label">Modifier Group</label>
                        <select name="modifier_group_id" id="mod_option_group" class="form-select" required>
                            <option value="0">No group yet - create reusable modifier only</option>
                            <?php foreach ($modifierGroups as $g): ?>
                                <option value="<?php echo (int)$g['id']; ?>"><?php echo h($g['group_name']); ?> (<?php echo h($g['group_type']); ?>)</option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="mb-2">
                        <label class="form-label">Parent Option / Depth</label>
                        <select name="parent_modifier_id" id="mod_option_parent" class="form-select">
                            <option value="0">Top-level option</option>
                            <?php foreach ($mods as $m): ?>
                                <option value="<?php echo (int)$m['id']; ?>" data-group="<?php echo (int)($m['modifier_group_id'] ?? 0); ?>"><?php echo h(($m['group_name'] ? $m['group_name'].' > ' : '') . $m['modifier_name']); ?></option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">Optional. Use parent option for depth, e.g. Cheese &gt; Extra Cheddar. You can link this modifier to groups later.</div>
                    </div>
                    <div class="row g-2">
                        <div class="col-7"><label class="form-label">Option Name</label><input name="modifier_name" id="mod_option_name" class="form-control" placeholder="Rare, Medium, Double shot, No ice" required></div>
                        <div class="col-5"><label class="form-label">Price +/-</label><input type="number" step="0.01" name="price_delta" id="mod_option_price" class="form-control" value="0.00"></div>
                    </div>
                    <div class="row g-2 mt-1">
                        <div class="col-4"><label class="form-label">Prefixes?</label><select name="prefix_allowed" id="mod_option_prefix" class="form-select"><option value="1">Yes</option><option value="0">No</option></select></div>
                        <div class="col-4"><label class="form-label">Sort</label><input type="number" name="sort_order" id="mod_option_sort" class="form-control" value="1"></div>
                        <div class="col-4"><label class="form-label">Active</label><select name="is_active" id="mod_option_active" class="form-select"><option value="1">Yes</option><option value="0">No</option></select></div>
                    </div>
                    <button class="btn btn-outline-primary w-100 mt-2">Save Reusable Modifier</button>
                    <button type="button" class="btn btn-light w-100 mt-1" id="clearModifierOptionBtn">Clear Modifier</button>
                </form>
                <form method="post" class="bulk-modifier-form mt-3">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="save_bulk_modifiers">
                    <label class="form-label">Bulk Create Modifiers</label>
                    <textarea name="bulk_modifiers" class="form-control" rows="4" placeholder="No ice&#10;Extra cheese:1.00&#10;Medium rare&#10;Double shot:3.00"></textarea>
                    <div class="form-text">One modifier per line. Use <strong>Name:Price</strong> when there is an extra charge.</div>
                    <button class="btn btn-outline-success w-100 mt-2"><i class="bi bi-plus-circle me-1"></i>Create Multiple Modifiers</button>
                </form>
                <hr>
                <div class="modifier-option-list enhanced-option-list" id="allModifierOptionsList">
                    <?php foreach ($modifierGroups as $g): ?>
                        <?php $groupMods = $modsByGroup[(int)$g['id']] ?? []; ?>
                        <div class="modifier-option-group-block" data-group-id="<?php echo (int)$g['id']; ?>">
                            <div class="modifier-option-group-head">
                                <div>
                                    <div class="fw-bold"><?php echo h($g['group_name']); ?></div>
                                    <div class="small text-muted"><?php echo count($groupMods); ?> option(s)</div>
                                </div>
                                <button type="button" class="btn btn-sm btn-outline-primary focus-modifier-group" data-group-id="<?php echo (int)$g['id']; ?>">View</button>
                            </div>
                            <div class="modifier-chip-grid">
                                <?php foreach ($groupMods as $m): ?>
                                    <span class="modifier-chip-wrap">
                                        <button type="button" class="modifier-chip edit-mod-option <?php echo ((int)($m['parent_modifier_id'] ?? 0)>0?'child-option':''); ?>" data-group-id="<?php echo (int)$g['id']; ?>" data-json='<?php echo h(json_encode($m)); ?>'>
                                            <span><?php echo ((int)($m['parent_modifier_id'] ?? 0)>0?'↳ ':''); ?><?php echo h($m['modifier_name']); ?></span>
                                            <?php if ((float)$m['price_delta'] != 0): ?><em><?php echo money_fmt($m['price_delta']); ?></em><?php endif; ?>
                                        </button>
                                        <?php if (!empty($m['_can_delete'])): ?>
                                            <form method="post" class="d-inline" onsubmit="return confirm('Delete this unused modifier option?');" onclick="event.stopPropagation();">
                                                <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                                <input type="hidden" name="action" value="delete_unused_modifier">
                                                <input type="hidden" name="id" value="<?php echo (int)$m['id']; ?>">
                                                <button type="submit" class="modifier-mini-delete" title="Delete unused modifier"><i class="bi bi-trash"></i></button>
                                            </form>
                                        <?php endif; ?>
                                    </span>
                                <?php endforeach; ?>
                                <?php if (!$groupMods): ?><span class="text-muted small">No options in this group yet.</span><?php endif; ?>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>
    </div>

    <div class="col-xl-8">
        <div class="card panel-card elite-focus-card" id="item-editor-card">
            <div class="card-header"><h5 class="mb-0">Add / Edit Menu Item</h5></div>
            <div class="card-body">
                <form method="post" class="row g-2" id="itemForm">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="save_item">
                    <input type="hidden" name="id" id="item_id">
                    <div class="col-md-5">
                        <label class="form-label">Category / Subcategory</label>
                        <select name="category_id" id="item_cat" class="form-select" required>
                            <option value="">Select category</option>
                            <?php foreach ($categories as $c): ?>
                                <option value="<?php echo (int)$c['id']; ?>" data-role="<?php echo h($c['printer_role']); ?>" data-color="<?php echo h($c['button_color'] ?? ''); ?>" data-path="<?php echo h($c['path_label']); ?>">
                                    <?php echo h(str_repeat('— ', (int)($c['computed_depth'] ?? 0)) . ($c['path_label'] ?? $c['category_name'])); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text" id="itemBreadcrumb">Attach items at any category depth.</div>
                    </div>
                    <div class="col-md-4"><label class="form-label">Menu Item</label><input name="item_name" id="item_name" class="form-control" required></div>
                    <div class="col-md-3"><label class="form-label">Code</label><input name="item_code" id="item_code" class="form-control"></div>
                    <div class="col-md-3"><label class="form-label">Price</label><input type="number" step="0.01" name="price" id="item_price" class="form-control" required></div>
                    <div class="col-md-3"><label class="form-label">Tax %</label><input type="number" step="0.0001" name="tax_rate" id="item_tax" class="form-control" value="0"></div>
                    <div class="col-md-3"><label class="form-label">Printer Role</label><select name="printer_role" id="item_role" class="form-select"><option value="kitchen">Kitchen</option><option value="bar">Bar</option><option value="dessert">Dessert</option><option value="master">Master</option></select></div>
                    <div class="col-md-3">
                        <label class="form-label">Button Color</label>
                        <div class="input-group">
                            <input name="button_color" id="item_color" class="form-control" list="buttonColorOptions" placeholder="auto / blue / #334155">
                            <span class="input-group-text color-preview-dot" id="itemColorPreview"></span>
                        </div>
                    </div>
                    <div class="col-md-5">
                        <label class="form-label">Linked Inventory Item</label>
                        <div class="d-flex gap-2 align-items-start">
                            <div class="flex-grow-1">
                                <select name="inventory_item_id" id="item_inv" class="form-select">
                                    <option value="0">Not linked</option>
                                    <?php foreach ($inventory as $it): ?>
                                        <option value="<?php echo (int)$it['id']; ?>"
                                                data-price="<?php echo h($it['selling_price'] ?? 0); ?>">
                                            <?php echo h($it['item_name']); ?>
                                            <?php echo $it['item_code'] ? ' - ' . h($it['item_code']) : ''; ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                                <div class="form-text" id="itemInventoryLinkStatus">
                                    Select an inventory item to link stock deduction, or leave as Not linked.
                                </div>
                            </div>
                            <button type="button"
                                    class="btn btn-outline-danger"
                                    id="item_delink_inventory"
                                    style="display:none;white-space:nowrap;"
                                    title="Remove the current inventory link">
                                <i class="bi bi-link-45deg me-1"></i>Delink
                            </button>
                        </div>
                    </div>
                    <div class="col-md-3"><label class="form-label">Tags</label><input name="tags" id="item_tags" class="form-control" placeholder="vegan, spicy"></div>
                    <div class="col-md-2"><label class="form-label">Food?</label><select name="is_food" id="item_food" class="form-select"><option value="0">No</option><option value="1">Yes</option></select></div>
                    <div class="col-md-2"><label class="form-label">Bar?</label><select name="is_bar" id="item_bar" class="form-select"><option value="0">No</option><option value="1">Yes</option></select></div>
                    <div class="col-12"><label class="form-label">Description</label><input name="description" id="item_desc" class="form-control"></div>
                    <div class="col-md-2"><label class="form-label">Sort</label><input type="number" name="sort_order" id="item_sort" class="form-control" value="1"></div>
                    <div class="col-md-2"><label class="form-label">Selectable?</label><select name="is_selectable" id="item_selectable" class="form-select"><option value="1">Yes</option><option value="0">No</option></select></div>
                    <div class="col-md-2"><label class="form-label">Active</label><select name="is_active" id="item_active" class="form-select"><option value="1">Yes</option><option value="0">No</option></select></div>
                    <div class="col-md-6">
                        <label class="form-label">Modifier Groups for this Item</label>
                        <input type="hidden" name="modifier_group_order" id="item_modifier_group_order" value="">
                        <select name="modifier_group_ids[]" id="item_modifier_groups" class="form-select" multiple size="6">
                            <?php foreach ($modifierGroups as $g): ?>
                                <option value="<?php echo (int)$g['id']; ?>"
                                        data-name="<?php echo h($g['group_name']); ?>"
                                        data-type="<?php echo h($g['group_type']); ?>"
                                        data-min="<?php echo (int)$g['min_select']; ?>"
                                        data-max="<?php echo (int)$g['max_select']; ?>"
                                        data-sort="<?php echo (int)$g['sort_order']; ?>">
                                    <?php echo h($g['group_name']); ?> - <?php echo h($g['group_type']); ?> <?php echo (int)$g['min_select']; ?>-<?php echo ((int)$g['max_select']===0?'∞':(int)$g['max_select']); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">Attach groups, then arrange the prompt order below. Planner will ask in this sequence.</div>
                        <div class="selected-group-order-box mt-2">
                            <div class="d-flex justify-content-between align-items-center mb-1">
                                <strong class="small text-dark">Prompt sequence</strong>
                                <button type="button" class="btn btn-sm btn-outline-secondary py-0" id="sortGroupsBySetupBtn">Use setup sort</button>
                            </div>
                            <div id="selectedModifierGroupOrder" class="selected-group-order-list">
                                <div class="text-muted small">Select modifier groups above to build the prompt order.</div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <label class="form-label">Legacy Direct Options</label>
                        <select name="modifier_ids[]" id="item_modifiers" class="form-select" multiple size="6">
                            <?php foreach ($mods as $m): ?>
                                <option value="<?php echo (int)$m['id']; ?>"><?php echo h(($m['group_name'] ? $m['group_name'].' > ' : '') . $m['modifier_name']); ?> <?php echo ((float)$m['price_delta'] != 0 ? '(' . money_fmt($m['price_delta']) . ')' : ''); ?></option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">Kept for backwards compatibility. Prefer groups above.</div>
                    </div>
                    <div class="col-12 d-flex align-items-end justify-content-end gap-2">
                        <button class="btn btn-primary">Save Item</button>
                        <button type="button" class="btn btn-light" id="clearItemBtn">Clear</button>
                    </div>
                </form>
            </div>
        </div>

        <div class="card panel-card mt-3 elite-collapsible" id="pos-preview-card" data-default-collapsed="1">
            <div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
                <h5 class="mb-0">POS Drill-down Preview</h5>
                <input type="search" id="menuSearch" class="form-control form-control-sm pos-search" placeholder="Search items / tags / category...">
            </div>
            <div class="card-body">
                <div class="breadcrumb-bar" id="posBreadcrumb">Root</div>
                <div class="drill-grid" id="categoryDrill"></div>
                <hr>
                <div class="drill-grid" id="itemDrill"></div>
            </div>
        </div>

        <div class="card panel-card mt-3 elite-focus-card" id="menu-items-card">
            <div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
                <h5 class="mb-0">Menu Items</h5>
                <span class="small text-muted">Showing <?php echo count($items); ?> of <?php echo (int)$itemTotalCount; ?></span>
            </div>
            <div class="card-body border-bottom">
                <?php
                    $activeMenuFilterCount = 0;
                    foreach ([
                        $itemSearchFilter,
                        $itemCategoryFilter,
                        $itemRoleFilter,
                        $itemStatusFilter,
                        $itemFoodBarFilter,
                        $itemSelectableFilter,
                        $itemInventoryFilter,
                        $itemRecipeFilter
                    ] as $activeFilterValue) {
                        if ((string)$activeFilterValue !== '' && (int)$activeFilterValue !== 0) {
                            $activeMenuFilterCount++;
                        }
                    }
                ?>
                <?php if ($activeMenuFilterCount > 0): ?>
                    <div class="menu-active-filter-banner">
                        <div>
                            <i class="bi bi-funnel-fill me-2"></i>
                            <strong><?php echo $activeMenuFilterCount; ?> active filter<?php echo $activeMenuFilterCount === 1 ? '' : 's'; ?></strong>
                            <span>Your search results will remain until you remove the filters.</span>
                        </div>
                        <a href="menu.php?reset_menu_filters=1" class="btn btn-sm btn-outline-danger">
                            <i class="bi bi-x-circle me-1"></i>Remove Filters
                        </a>
                    </div>
                <?php endif; ?>
                <form method="get" class="row g-2 align-items-end menu-item-filter-form">
                    <div class="col-lg-3 col-md-6">
                        <label class="form-label">Search Items</label>
                        <input type="text" name="item_q" class="form-control form-control-sm" value="<?php echo h($itemSearchFilter); ?>" placeholder="Name, code, tag, category...">
                    </div>
                    <div class="col-lg-3 col-md-6">
                        <label class="form-label">Category</label>
                        <select name="item_category_id" class="form-select form-select-sm">
                            <option value="0">All categories</option>
                            <?php foreach ($categories as $catOpt): ?>
                                <option value="<?php echo (int)$catOpt['id']; ?>" <?php echo $itemCategoryFilter === (int)$catOpt['id'] ? 'selected' : ''; ?>>
                                    <?php echo h($catOpt['path_label'] ?? $catOpt['category_name']); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-lg-2 col-md-4">
                        <label class="form-label">Printer Role</label>
                        <select name="item_printer_role" class="form-select form-select-sm">
                            <option value="">All roles</option>
                            <option value="__blank__" <?php echo $itemRoleFilter === '__blank__' ? 'selected' : ''; ?>>No role set</option>
                            <?php foreach ($itemRoleOptions as $roleKey => $roleLabel): ?>
                                <option value="<?php echo h($roleKey); ?>" <?php echo $itemRoleFilter === $roleKey ? 'selected' : ''; ?>><?php echo h($roleLabel); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-lg-2 col-md-4">
                        <label class="form-label">Status</label>
                        <select name="item_status" class="form-select form-select-sm">
                            <option value="">All</option>
                            <option value="1" <?php echo $itemStatusFilter === '1' ? 'selected' : ''; ?>>Active</option>
                            <option value="0" <?php echo $itemStatusFilter === '0' ? 'selected' : ''; ?>>Inactive</option>
                        </select>
                    </div>
                    <div class="col-lg-2 col-md-4">
                        <label class="form-label">Type</label>
                        <select name="item_food_bar" class="form-select form-select-sm">
                            <option value="">All</option>
                            <option value="food" <?php echo $itemFoodBarFilter === 'food' ? 'selected' : ''; ?>>Food only</option>
                            <option value="bar" <?php echo $itemFoodBarFilter === 'bar' ? 'selected' : ''; ?>>Bar only</option>
                            <option value="both" <?php echo $itemFoodBarFilter === 'both' ? 'selected' : ''; ?>>Food & Bar</option>
                            <option value="none" <?php echo $itemFoodBarFilter === 'none' ? 'selected' : ''; ?>>Neither</option>
                        </select>
                    </div>
                    <div class="col-lg-2 col-md-4">
                        <label class="form-label">Selectable</label>
                        <select name="item_selectable" class="form-select form-select-sm">
                            <option value="">All</option>
                            <option value="1" <?php echo $itemSelectableFilter === '1' ? 'selected' : ''; ?>>Selectable</option>
                            <option value="0" <?php echo $itemSelectableFilter === '0' ? 'selected' : ''; ?>>Not selectable</option>
                        </select>
                    </div>
                    <div class="col-lg-2 col-md-4">
                        <label class="form-label">Direct Inventory</label>
                        <select name="item_inventory_link" class="form-select form-select-sm">
                            <option value="">All items</option>
                            <option value="linked" <?php echo $itemInventoryFilter === 'linked' ? 'selected' : ''; ?>>Direct item linked</option>
                            <option value="unlinked" <?php echo $itemInventoryFilter === 'unlinked' ? 'selected' : ''; ?>>No direct link</option>
                            <option value="none" <?php echo $itemInventoryFilter === 'none' ? 'selected' : ''; ?>>No stock control at all</option>
                        </select>
                    </div>
                    <div class="col-lg-2 col-md-4">
                        <label class="form-label">Recipe</label>
                        <select name="item_recipe_link" class="form-select form-select-sm">
                            <option value="">All items</option>
                            <option value="linked" <?php echo $itemRecipeFilter === 'linked' ? 'selected' : ''; ?>>Has active recipe</option>
                            <option value="unlinked" <?php echo $itemRecipeFilter === 'unlinked' ? 'selected' : ''; ?>>No active recipe</option>
                        </select>
                    </div>
                    <div class="col-lg-2 col-md-4 d-grid">
                        <button class="btn btn-primary btn-sm"><i class="bi bi-funnel me-1"></i>Filter</button>
                    </div>
                    <div class="col-lg-2 col-md-4 d-grid">
                        <a class="btn btn-light btn-sm" href="menu.php"><i class="bi bi-x-circle me-1"></i>Reset</a>
                    </div>
                </form>

                <form method="post" id="delinkInventoryForm" class="d-none">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="delink_inventory_item">
                    <input type="hidden" name="id" id="delink_inventory_item_id" value="">
                </form>
            </div>
            <div class="table-responsive menu-table-wrap">
                <table class="table table-modern mb-0">
                    <thead><tr><th>Category Path</th><th>Item</th><th>Stock Control</th><th>Tags</th><th>Role</th><th>Type</th><th class="text-end">Price</th><th>Status</th><th></th></tr></thead>
                    <tbody>
                    <?php if (!$items): ?>
                        <tr><td colspan="9" class="text-center text-muted py-4">No menu items match the selected filters.</td></tr>
                    <?php endif; ?>
                    <?php foreach ($items as $it): ?>
                        <tr>
                            <td><?php echo h($it['category_path'] ?: $it['category_name']); ?></td>
                            <td><strong><?php echo h($it['item_name']); ?></strong><div class="small text-muted"><?php echo h($it['description']); ?></div></td>
                            <td>
                                <?php
                                    $directInventoryId = (int)($it['inventory_item_id'] ?? 0);
                                    $directInventoryName = trim((string)($it['inventory_item_name'] ?? ''));
                                    $directInventoryCode = trim((string)($it['inventory_item_code'] ?? ''));
                                    $recipeCount = (int)($it['active_recipe_count'] ?? 0);
                                    $recipeNames = trim((string)($it['active_recipe_names'] ?? ''));
                                ?>
                                <?php if ($directInventoryId > 0): ?>
                                    <span class="badge text-bg-success">
                                        <i class="bi bi-box-seam me-1"></i>Direct inventory
                                    </span>
                                    <div class="small text-muted mt-1">
                                        Inventory #<?php echo $directInventoryId; ?>
                                        <?php if ($directInventoryCode !== ''): ?>
                                            &nbsp;(<span class="fw-semibold"><?php echo h($directInventoryCode); ?></span>)
                                        <?php endif; ?>
                                        <?php if ($directInventoryName !== ''): ?>
                                            &nbsp;&ndash;&nbsp;<strong><?php echo h($directInventoryName); ?></strong>
                                        <?php endif; ?>
                                    </div>
                                <?php endif; ?>

                                <?php if ($recipeCount > 0): ?>
                                    <span class="badge text-bg-primary <?php echo $directInventoryId > 0 ? 'ms-1' : ''; ?>">
                                        <i class="bi bi-journal-check me-1"></i><?php echo $recipeCount; ?> recipe<?php echo $recipeCount === 1 ? '' : 's'; ?>
                                    </span>
                                    <?php if ($recipeNames !== ''): ?>
                                        <div class="small text-muted mt-1 recipe-name-preview" title="<?php echo h($recipeNames); ?>">
                                            <?php echo h($recipeNames); ?>
                                        </div>
                                    <?php endif; ?>
                                <?php endif; ?>

                                <?php if ($directInventoryId <= 0 && $recipeCount <= 0): ?>
                                    <span class="badge text-bg-warning"><i class="bi bi-exclamation-triangle me-1"></i>No stock control</span>
                                    <div class="small text-muted mt-1">No direct item or active recipe</div>
                                <?php elseif ($directInventoryId <= 0 && $recipeCount > 0): ?>
                                    <div class="small text-success mt-1"><i class="bi bi-check-circle me-1"></i>Stock deducted through recipe</div>
                                <?php endif; ?>
                            </td>
                            <td><span class="small text-muted"><?php echo h($it['tags'] ?? ''); ?></span></td>
                            <td><?php echo h($it['printer_role']); ?></td>
                            <td>
                                <?php if ((int)($it['is_food'] ?? 0) === 1): ?><span class="badge text-bg-success">Food</span><?php endif; ?>
                                <?php if ((int)($it['is_bar'] ?? 0) === 1): ?><span class="badge text-bg-info">Bar</span><?php endif; ?>
                                <?php if ((int)($it['is_selectable'] ?? 1) === 0): ?><span class="badge text-bg-warning">Not selectable</span><?php endif; ?>
                            </td>
                            <td class="text-end"><?php echo money_fmt($it['price']); ?></td>
                            <td><?php echo (int)$it['is_active'] ? '<span class="badge text-bg-success">Active</span>' : '<span class="badge text-bg-danger">Inactive</span>'; ?></td>
                            <td class="text-end">
                                <div class="d-inline-flex gap-1 align-items-center justify-content-end">
                                    <button class="btn btn-sm btn-outline-primary edit-item" data-json='<?php echo h(json_encode($it)); ?>'>Edit</button>
                                    <?php if ((int)($it['inventory_item_id'] ?? 0) > 0): ?>
                                        <form method="post"
                                              class="d-inline"
                                              onsubmit="return confirm('Remove the inventory link from <?php echo h(addslashes((string)$it['item_name'])); ?>? The menu item will remain sellable, but direct linked-item stock deduction will stop until another inventory item is linked.');">
                                            <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                            <input type="hidden" name="action" value="delink_inventory_item">
                                            <input type="hidden" name="id" value="<?php echo (int)$it['id']; ?>">
                                            <button type="submit" class="btn btn-sm btn-outline-warning" title="Delink inventory item">
                                                <i class="bi bi-link-45deg me-1"></i>Delink
                                            </button>
                                        </form>
                                    <?php endif; ?>
                                    <?php if (!empty($it['_can_delete'])): ?>
                                        <form method="post" class="d-inline" onsubmit="return confirm('Delete this unused menu item?');">
                                            <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                                            <input type="hidden" name="action" value="delete_unused_menu_item">
                                            <input type="hidden" name="id" value="<?php echo (int)$it['id']; ?>">
                                            <button type="submit" class="btn btn-sm btn-outline-danger">Delete</button>
                                        </form>
                                    <?php else: ?>
                                        <span class="badge text-bg-light border" title="Used or linked, cannot delete">Used</span>
                                    <?php endif; ?>
                                </div>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<style>
.compact-restaurant-hero{padding:12px 16px!important;margin-bottom:10px!important}.compact-restaurant-hero .hero-title{font-size:1.35rem!important}.compact-restaurant-hero .hero-subtitle{font-size:.82rem!important}.compact-restaurant-hero .btn{margin-left:3px;margin-bottom:3px}.panel-card{border-radius:16px;box-shadow:0 10px 24px rgba(15,23,42,.06);border:1px solid #e5e7eb;overflow:hidden}.panel-card .card-header{background:#fff;padding:10px 12px;border-bottom:1px solid #eef2f7}.panel-card .card-header h5{font-size:.95rem;font-weight:900}.panel-card .card-body{padding:12px}.form-label{font-size:.72rem;font-weight:800;color:#334155;margin-bottom:3px}.form-control,.form-select{border-radius:10px;font-size:.84rem}.table-modern thead th{font-size:.7rem;text-transform:uppercase;color:#64748b;background:#f8fafc;position:sticky;top:0;z-index:4;white-space:nowrap}.menu-table-wrap{max-height:470px;overflow:auto}.menu-tree-box{max-height:330px;overflow:auto}.menu-tree-list{list-style:none;padding-left:0;margin:0}.tree-children{margin-left:14px;border-left:1px dashed #cbd5e1;padding-left:7px}.menu-tree-row{display:flex;align-items:center;gap:5px;margin-bottom:5px;border:1px solid transparent;border-radius:12px;padding:2px}.menu-tree-node.dragging{opacity:.45}.menu-tree-row.drag-over,.root-drop-zone.drag-over{border-color:#2563eb!important;background:#eff6ff!important;box-shadow:0 8px 18px rgba(37,99,235,.14)}.drag-handle{cursor:grab;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center}.drag-handle:active{cursor:grabbing}.drop-hint{display:none;font-size:.68rem;font-weight:900;color:#2563eb;background:#dbeafe;border-radius:999px;padding:2px 7px}.menu-tree-row.drag-over .drop-hint{display:inline-block}.root-drop-zone{border:1px dashed #93c5fd;background:#eff6ff;color:#1d4ed8;border-radius:14px;padding:9px 11px;font-size:.78rem;font-weight:900}.tree-toggle{width:30px}.breadcrumb-bar{background:#f8fafc;border:1px solid #e2e8f0;border-radius:999px;padding:7px 11px;font-size:.8rem;font-weight:800;color:#334155;margin-bottom:10px}.drill-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(145px,1fr));gap:9px}.drill-card-wrap{position:relative}.drill-card-wrap .drill-btn{width:100%;height:100%}.drill-edit-btn{position:absolute;right:7px;top:7px;z-index:3;border:0;border-radius:999px;background:rgba(255,255,255,.92);color:#0f172a;width:30px;height:30px;display:flex;align-items:center;justify-content:center;box-shadow:0 6px 15px rgba(15,23,42,.22)}.drill-edit-btn:hover{background:#fff;transform:scale(1.04)}.drill-btn,.item-btn{border:0;border-radius:15px;padding:10px 11px;text-align:left;box-shadow:0 9px 20px rgba(15,23,42,.12);min-height:72px;color:#fff;position:relative;overflow:hidden;transition:.15s ease}.item-btn{min-height:82px}.drill-btn:before,.item-btn:before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(255,255,255,.18),rgba(255,255,255,0));pointer-events:none}.drill-btn:hover,.item-btn:hover{transform:translateY(-2px);filter:brightness(1.05);box-shadow:0 13px 26px rgba(15,23,42,.18)}.drill-btn strong,.item-btn strong{display:block;color:#fff;position:relative;z-index:1}.drill-btn span,.item-btn span{display:block;font-size:.72rem;color:rgba(255,255,255,.86);position:relative;z-index:1}.item-btn .tag-pill{background:rgba(255,255,255,.20);border-color:rgba(255,255,255,.32);color:#fff}.color-preview-dot{width:42px;min-width:42px;border-radius:0 10px 10px 0!important;background:#334155;border-left:0!important}.pos-search{max-width:320px}.tag-pill{display:inline-block;background:#f1f5f9;border:1px solid #e2e8f0;border-radius:999px;padding:1px 6px;margin:1px;font-size:.68rem}

/* Clean modifier layout */
.modifier-toolbar{align-items:stretch!important}.modifier-toolbar .input-group-text{border-radius:10px 0 0 10px}.modifier-group-list{max-height:300px;overflow:auto}.modifier-option-list{max-height:330px;overflow:auto}.premium-modifier-groups{display:flex;flex-direction:column;gap:8px;padding-right:2px}.modifier-group-card{width:100%;border:1px solid #e2e8f0;background:#fff;border-radius:14px;padding:10px;text-align:left;transition:.15s ease;box-shadow:0 6px 14px rgba(15,23,42,.045);display:block;cursor:pointer}.modifier-group-card:hover,.modifier-group-card.active{border-color:#2563eb;background:#f8fbff;box-shadow:0 10px 20px rgba(37,99,235,.10)}.mg-main{display:flex;gap:9px;align-items:flex-start}.mg-icon{width:32px;height:32px;border-radius:11px;background:#dbeafe;color:#1d4ed8;display:flex;align-items:center;justify-content:center;flex:0 0 auto}.mg-copy{min-width:0}.mg-title{font-weight:900;color:#0f172a;line-height:1.15}.mg-sub{display:flex;flex-wrap:wrap;gap:5px;align-items:center;font-size:.7rem;color:#64748b;margin-top:4px}.mg-preview{display:flex;flex-wrap:wrap;gap:4px;margin-top:7px;padding-left:41px}.mg-preview span{background:#f1f5f9;border:1px solid #e2e8f0;color:#334155;border-radius:999px;padding:2px 7px;font-size:.67rem;font-weight:750}.modifier-delete-row{margin-top:8px;padding-left:41px;display:flex;align-items:center;gap:8px}.modifier-delete-row .btn{padding:2px 8px;font-size:.68rem}.modifier-detail-panel{border:1px solid #c7d2fe;background:linear-gradient(180deg,#f5f7ff,#fff);border-radius:16px;padding:11px}.modifier-detail-empty{text-align:center;color:#64748b;padding:12px}.modifier-detail-empty i{font-size:1.35rem;display:block;color:#2563eb}.modifier-detail-head{display:flex;justify-content:space-between;gap:10px;align-items:flex-start;border-bottom:1px solid #dbe4ff;padding-bottom:8px;margin-bottom:10px}.modifier-detail-title{font-weight:900;color:#0f172a;font-size:1rem}.modifier-detail-meta{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}.modifier-detail-actions{display:flex;gap:6px;flex-wrap:wrap}.modifier-search-mini{margin-bottom:10px}.modifier-tree{display:flex;flex-direction:column;gap:8px}.modifier-parent-card{border:1px solid #e2e8f0;background:#fff;border-radius:13px;padding:9px}.modifier-parent-line{display:flex;justify-content:space-between;gap:8px;align-items:center}.modifier-parent-name{font-weight:850;color:#0f172a}.modifier-price-pill{background:#ecfdf5;color:#047857;border:1px solid #bbf7d0;border-radius:999px;padding:2px 7px;font-size:.7rem;font-weight:900}.modifier-child-wrap{display:flex;flex-wrap:wrap;gap:5px;margin-top:7px;padding-left:9px;border-left:2px solid #dbeafe}.modifier-child-chip,.modifier-chip{border:1px solid #e2e8f0;background:#f8fafc;border-radius:999px;padding:5px 8px;font-size:.73rem;color:#334155;display:inline-flex;gap:6px;align-items:center;cursor:pointer}.modifier-child-chip:hover,.modifier-chip:hover{background:#e0f2fe;border-color:#38bdf8}.modifier-child-chip em,.modifier-chip em{font-style:normal;color:#047857;font-weight:900}.enhanced-option-list{display:flex;flex-direction:column;gap:9px}.modifier-option-group-block{border:1px solid #e2e8f0;border-radius:14px;padding:9px;background:#fff}.modifier-option-group-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.modifier-chip-grid{display:flex;flex-wrap:wrap;gap:6px}.modifier-chip.child-option{background:#f8fafc}.modifier-chip-wrap{display:inline-flex;align-items:center;gap:3px}.modifier-mini-delete{border:1px solid #fecaca;background:#fff;color:#dc2626;border-radius:999px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;font-size:.7rem}.modifier-mini-delete:hover{background:#fee2e2}.edit-mod-option{cursor:pointer}.edit-mod-option:hover,.edit-mod-group:hover{background:#f8fbff}.hidden-by-search{display:none!important}.menu-item-filter-form .form-control,.menu-item-filter-form .form-select{min-height:31px}.menu-item-filter-form .btn{min-height:31px;font-weight:800}
.selected-group-order-box{border:1px solid #dbeafe;background:#f8fbff;border-radius:14px;padding:9px}.selected-group-order-list{display:flex;flex-direction:column;gap:6px;min-height:40px}.selected-group-row{display:flex;align-items:center;justify-content:space-between;gap:8px;border:1px solid #e2e8f0;background:#fff;border-radius:12px;padding:7px 8px;box-shadow:0 4px 10px rgba(15,23,42,.035)}.selected-group-row .group-seq-no{width:26px;height:26px;border-radius:999px;background:#2563eb;color:#fff;display:inline-flex;align-items:center;justify-content:center;font-size:.72rem;font-weight:900;flex:0 0 auto}.selected-group-main{display:flex;align-items:center;gap:7px;min-width:0}.selected-group-title{font-weight:850;color:#0f172a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.selected-group-meta{font-size:.7rem;color:#64748b}.selected-group-actions{display:flex;align-items:center;gap:4px;flex:0 0 auto}.selected-group-actions .btn{padding:1px 6px;font-size:.72rem}

@media (min-width:1200px){.col-xl-4{width:34%}.col-xl-8{width:66%}}@media (max-width:1199.98px){.modifier-group-list,.modifier-option-list,.menu-tree-box,.menu-table-wrap{max-height:none}.modifier-delete-row,.mg-preview{padding-left:0}}

/* Elite workspace simplification */
.menu-workspace-grid{
    align-items:start;
}
.menu-workspace-bar{
    position:sticky;
    top:72px;
    z-index:35;
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:16px;
    margin:0 0 12px;
    padding:12px 14px;
    border:1px solid #dbe3ef;
    border-radius:18px;
    background:rgba(255,255,255,.96);
    box-shadow:0 12px 30px rgba(15,23,42,.08);
    backdrop-filter:blur(14px);
}
.menu-workspace-copy{
    min-width:240px;
}
.menu-workspace-copy strong{
    display:block;
    color:#0f172a;
    font-size:.95rem;
    line-height:1.2;
}
.menu-workspace-copy small{
    display:block;
    color:#64748b;
    font-size:.72rem;
    margin-top:2px;
}
.menu-workspace-kicker{
    display:block;
    color:#2563eb;
    font-size:.63rem;
    font-weight:950;
    text-transform:uppercase;
    letter-spacing:.1em;
    margin-bottom:2px;
}
.menu-workspace-actions{
    display:flex;
    align-items:center;
    justify-content:flex-end;
    gap:6px;
    flex-wrap:wrap;
}
.workspace-jump{
    border:1px solid #dbe3ef;
    background:#f8fafc;
    color:#334155;
    border-radius:12px;
    padding:7px 9px;
    min-width:70px;
    display:inline-flex;
    flex-direction:column;
    align-items:center;
    gap:2px;
    font-size:.66rem;
    font-weight:900;
    transition:.16s ease;
}
.workspace-jump i{
    font-size:.92rem;
}
.workspace-jump:hover,
.workspace-jump.active{
    border-color:#2563eb;
    background:#eff6ff;
    color:#1d4ed8;
    transform:translateY(-1px);
}
.panel-card{
    transition:box-shadow .18s ease,border-color .18s ease,transform .18s ease;
}
.panel-card:hover{
    border-color:#cbd5e1;
}
.elite-focus-card{
    box-shadow:0 14px 34px rgba(15,23,42,.075);
}
.elite-collapsible>.card-header{
    cursor:pointer;
    user-select:none;
}
.elite-collapse-toggle{
    width:30px;
    height:30px;
    border:1px solid #dbe3ef;
    border-radius:10px;
    background:#f8fafc;
    color:#475569;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    flex:0 0 auto;
}
.elite-collapse-toggle:hover{
    background:#eff6ff;
    color:#2563eb;
    border-color:#bfdbfe;
}
.elite-collapsible.is-collapsed>.card-body,
.elite-collapsible.is-collapsed>.table-responsive,
.elite-collapsible.is-collapsed>.menu-table-wrap{
    display:none!important;
}
.elite-collapsible.is-collapsed{
    box-shadow:0 5px 14px rgba(15,23,42,.045);
}
.elite-collapsible.is-collapsed>.card-header{
    border-bottom:0;
}
.elite-collapsible.is-collapsed .elite-collapse-toggle i{
    transform:rotate(-90deg);
}
.elite-collapse-toggle i{
    transition:transform .16s ease;
}
.panel-card>.card-header{
    min-height:48px;
}
.panel-card>.card-header h5{
    letter-spacing:-.01em;
}
.card-header .elite-panel-subtitle{
    display:block;
    color:#64748b;
    font-size:.68rem;
    font-weight:600;
    margin-top:2px;
}
.menu-item-filter-form{
    padding:10px!important;
    background:#f8fafc!important;
    border:1px solid #e2e8f0!important;
    border-radius:14px!important;
}
.menu-table-wrap{
    border-top:1px solid #eef2f7;
}
.menu-table-wrap table tbody tr{
    transition:background .12s ease;
}
.menu-table-wrap table tbody tr:hover{
    background:#f8fbff;
}
.menu-table-wrap td{
    vertical-align:middle;
}
.import-export-card .card-body form{
    padding:10px;
    border:1px dashed #cbd5e1;
    border-radius:13px;
    background:#f8fafc;
}
#item-editor-card .card-body{
    background:linear-gradient(180deg,#fff,#fbfdff);
}
#menu-items-card{
    border-color:#cbd5e1;
}
#menu-items-card>.card-header{
    background:linear-gradient(180deg,#fff,#f8fafc);
}
.elite-panel-highlight{
    animation:elitePanelPulse 1.25s ease;
}
@keyframes elitePanelPulse{
    0%{box-shadow:0 0 0 0 rgba(37,99,235,.26)}
    45%{box-shadow:0 0 0 7px rgba(37,99,235,.08)}
    100%{box-shadow:0 12px 28px rgba(15,23,42,.07)}
}
@media (min-width:1200px){
    .menu-workspace-grid>.col-xl-4{
        width:30%;
    }
    .menu-workspace-grid>.col-xl-8{
        width:70%;
    }
}
@media (max-width:991.98px){
    .menu-workspace-bar{
        position:static;
        display:block;
    }
    .menu-workspace-actions{
        justify-content:flex-start;
        margin-top:10px;
    }
    .workspace-jump{
        min-width:64px;
        flex:1 1 70px;
    }
}


/* Full-width management-first menu workspace */
.menu-workspace-grid{
    display:block!important;
}
.menu-workspace-grid>.col-xl-4,
.menu-workspace-grid>.col-xl-8{
    width:100%!important;
    max-width:none!important;
    padding:0!important;
}
.menu-workspace-grid>.col-xl-4,
.menu-workspace-grid>.col-xl-8{
    display:contents;
}
.menu-workspace-grid>.card,
.menu-workspace-grid .panel-card{
    width:100%;
}
#menu-items-card{
    margin-top:0!important;
}
#item-editor-card{
    margin-top:14px!important;
}
#menu-items-card .menu-table-wrap{
    max-height:560px;
    overflow:auto;
}
#menu-items-card thead th{
    position:sticky;
    top:0;
    z-index:5;
    background:#f8fafc;
    box-shadow:0 1px 0 #e2e8f0;
}
.recipe-name-preview{
    max-width:280px;
    white-space:nowrap;
    overflow:hidden;
    text-overflow:ellipsis;
}
#menu-items-card .card-body{
    padding:12px;
}
.menu-item-filter-form .col-lg-2,
.menu-item-filter-form .col-lg-3{
    min-width:150px;
}
.menu-workspace-actions{
    flex-wrap:nowrap;
    overflow-x:auto;
    padding-bottom:2px;
}
.workspace-jump{
    flex:0 0 auto;
}
@media (max-width:767.98px){
    #menu-items-card .menu-table-wrap{
        max-height:none;
    }
    .menu-workspace-actions{
        flex-wrap:wrap;
    }
}


.menu-active-filter-banner{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:12px;
    padding:9px 11px;
    margin-bottom:9px;
    border:1px solid #bfdbfe;
    border-radius:12px;
    background:#eff6ff;
    color:#1e3a8a;
    font-size:.78rem;
}
.menu-active-filter-banner span{
    color:#475569;
    margin-left:6px;
}
@media (max-width:767.98px){
    .menu-active-filter-banner{
        align-items:flex-start;
        flex-direction:column;
    }
}

</style>

<!-- Tom Select: searchable dropdown for the (large) linked inventory list -->
<link href="https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/css/tom-select.bootstrap5.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/tom-select@2.3.1/dist/js/tom-select.complete.min.js"></script>

<script>
document.addEventListener('DOMContentLoaded', function(){
    const categories = <?php echo $categoryJson ?: '[]'; ?>;
    const items = <?php echo $itemsJson ?: '[]'; ?>;
    const modifierGroups = <?php echo $modifierGroupsJson ?: '[]'; ?>;
    const modifierOptions = <?php echo $modsJson ?: '[]'; ?>;

    // Convert the dense setup page into a focused workspace without removing
    // any existing functionality.
    (function setupEliteWorkspace(){
        const workspaceGrid = document.querySelector('.menu-workspace-grid');
        if (workspaceGrid) {
            const preferredOrder = [
                'menu-items-card',
                'item-editor-card',
                'category-tree-card',
                'category-editor-card',
                'modifier-groups-card',
                'modifier-options-card',
                'pos-preview-card',
                'import-export-card'
            ];

            preferredOrder.forEach(function(id){
                const card = document.getElementById(id);
                if (card) workspaceGrid.appendChild(card);
            });

            Array.from(workspaceGrid.children).forEach(function(child){
                if (child.classList && (child.classList.contains('col-xl-4') || child.classList.contains('col-xl-8'))) {
                    while (child.firstChild) workspaceGrid.appendChild(child.firstChild);
                    child.remove();
                }
            });
        }

        const storageKey = 'restaurant_menu_panel_state_v2';

        function loadState(){
            try { return JSON.parse(localStorage.getItem(storageKey) || '{}'); }
            catch(e){ return {}; }
        }
        function saveState(state){
            try { localStorage.setItem(storageKey, JSON.stringify(state)); }
            catch(e){}
        }
        const state = loadState();

        document.querySelectorAll('.elite-collapsible').forEach(card => {
            const header = card.querySelector(':scope > .card-header');
            if (!header) return;

            const cardId = card.id || '';
            const defaultCollapsed = card.dataset.defaultCollapsed === '1';
            const collapsed = Object.prototype.hasOwnProperty.call(state, cardId)
                ? !!state[cardId]
                : defaultCollapsed;

            const existingRight = header.querySelector('.elite-collapse-toggle');
            if (!existingRight) {
                const toggle = document.createElement('button');
                toggle.type = 'button';
                toggle.className = 'elite-collapse-toggle ms-auto';
                toggle.title = 'Show or hide this section';
                toggle.setAttribute('aria-label', 'Show or hide this section');
                toggle.innerHTML = '<i class="bi bi-chevron-down"></i>';
                header.appendChild(toggle);
            }

            card.classList.toggle('is-collapsed', collapsed);

            const toggleCard = function(e){
                if (e && (e.target.closest('a') || e.target.closest('button:not(.elite-collapse-toggle)') || e.target.closest('input') || e.target.closest('select'))) {
                    return;
                }
                card.classList.toggle('is-collapsed');
                state[cardId] = card.classList.contains('is-collapsed');
                saveState(state);
            };

            header.addEventListener('click', toggleCard);
        });

        document.querySelectorAll('.workspace-jump').forEach(btn => {
            btn.addEventListener('click', function(){
                const target = document.getElementById(this.dataset.jumpTarget || '');
                if (!target) return;

                if (target.classList.contains('is-collapsed')) {
                    target.classList.remove('is-collapsed');
                    state[target.id] = false;
                    saveState(state);
                }

                document.querySelectorAll('.workspace-jump').forEach(x => x.classList.remove('active'));
                this.classList.add('active');

                target.scrollIntoView({behavior:'smooth', block:'start'});
                target.classList.remove('elite-panel-highlight');
                void target.offsetWidth;
                target.classList.add('elite-panel-highlight');
                window.setTimeout(() => target.classList.remove('elite-panel-highlight'), 1400);
            });
        });

        // Add quiet descriptive subtitles to clarify each panel.
        const subtitles = {
            'import-export-card':'Bulk upload, download and maintenance tools',
            'category-tree-card':'Drag and organise the POS navigation hierarchy',
            'category-editor-card':'Create or update one category',
            'modifier-groups-card':'Build required, optional and default selections',
            'modifier-options-card':'Create reusable choices once and share them',
            'item-editor-card':'Create or update one sellable menu item',
            'pos-preview-card':'Preview the live button hierarchy',
            'menu-items-card':'Search, review, edit, link or delink items'
        };
        Object.keys(subtitles).forEach(id => {
            const card = document.getElementById(id);
            const title = card ? card.querySelector(':scope > .card-header h5') : null;
            if (title && !title.querySelector('.elite-panel-subtitle')) {
                const span = document.createElement('span');
                span.className = 'elite-panel-subtitle';
                span.textContent = subtitles[id];
                title.appendChild(span);
            }
        });
    })();

    const colorMap = {
        food:'#10b981', restaurant:'#10b981', main:'#10b981', grill:'#ef4444', pizza:'#f97316', burger:'#f59e0b', snack:'#84cc16',
        drinks:'#3b82f6', drink:'#3b82f6', bar:'#2563eb', cocktails:'#8b5cf6', cocktail:'#8b5cf6',
        wine:'#dc2626', wines:'#dc2626', beer:'#f59e0b', beers:'#f59e0b',
        hot:'#92400e', coffee:'#92400e', tea:'#92400e', dessert:'#ec4899', desserts:'#ec4899',
        spa:'#06b6d4', spar:'#06b6d4', curio:'#6366f1', special:'#f43f5e', specials:'#f43f5e',
        blue:'#3b82f6', green:'#10b981', emerald:'#10b981', purple:'#8b5cf6', red:'#dc2626',
        orange:'#f97316', amber:'#f59e0b', pink:'#ec4899', teal:'#14b8a6', cyan:'#06b6d4',
        slate:'#475569', grey:'#64748b', gray:'#64748b'
    };

    function buttonHex(value, fallbackText){
        value = String(value || '').trim().toLowerCase();
        fallbackText = String(fallbackText || '').trim().toLowerCase();
        if(/^#([a-f0-9]{3}|[a-f0-9]{6})$/i.test(value)) return value;
        if(colorMap[value]) return colorMap[value];
        for(const key in colorMap){
            if(fallbackText.includes(key)) return colorMap[key];
        }
        return '#334155';
    }

    function buttonBg(value, fallbackText){
        const hex = buttonHex(value, fallbackText);
        return 'linear-gradient(135deg,' + hex + ',' + shadeHex(hex, -22) + ')';
    }

    function shadeHex(hex, percent){
        hex = String(hex || '#334155').replace('#','');
        if(hex.length === 3) hex = hex.split('').map(x => x + x).join('');
        const n = parseInt(hex,16);
        let r = (n >> 16) + Math.round(255 * percent / 100);
        let g = ((n >> 8) & 255) + Math.round(255 * percent / 100);
        let b = (n & 255) + Math.round(255 * percent / 100);
        r = Math.max(0, Math.min(255, r)); g = Math.max(0, Math.min(255, g)); b = Math.max(0, Math.min(255, b));
        return '#' + (b | (g << 8) | (r << 16) | (1 << 24)).toString(16).slice(1);
    }

    function categoryById(id){
        id = parseInt(id || 0, 10) || 0;
        return categories.find(c => parseInt(c.id || 0, 10) === id) || null;
    }

    function disableInvalidParentOptions(editingId){
        const sel = document.getElementById('cat_parent_id');
        editingId = parseInt(editingId || 0, 10) || 0;
        if(!sel) return;

        const childMap = {};
        categories.forEach(c => {
            const pid = parseInt(c.parent_id || 0, 10) || 0;
            if(!childMap[pid]) childMap[pid] = [];
            childMap[pid].push(parseInt(c.id || 0, 10) || 0);
        });

        const descendants = new Set();
        function collect(id){
            (childMap[id] || []).forEach(childId => {
                if(childId && !descendants.has(childId)){
                    descendants.add(childId);
                    collect(childId);
                }
            });
        }
        if(editingId > 0) collect(editingId);

        [...sel.options].forEach(opt => {
            const v = parseInt(opt.value || 0, 10) || 0;
            opt.disabled = editingId > 0 && (v === editingId || descendants.has(v));
        });
    }

    function editCategoryObject(c, shouldScroll){
        if(!c) return;
        const id = parseInt(c.id || 0, 10) || 0;
        const parentId = parseInt(c.parent_id || 0, 10) || 0;

        if(typeof cat_id !== 'undefined') cat_id.value = id || '';
        if(typeof cat_name !== 'undefined') cat_name.value = c.category_name || '';
        if(typeof cat_parent_id !== 'undefined') cat_parent_id.value = parentId ? String(parentId) : '0';
        if(typeof cat_role !== 'undefined') cat_role.value = c.printer_role || 'kitchen';
        if(typeof cat_color !== 'undefined') cat_color.value = c.button_color || '';
        if(typeof cat_sort !== 'undefined') cat_sort.value = c.sort_order || 1;
        if(typeof cat_active !== 'undefined') cat_active.value = String(parseInt(c.is_active ?? 1, 10));
        disableInvalidParentOptions(id);
        updateCatBreadcrumb();
        updateColorPreview(cat_color, document.getElementById('catColorPreview'), [c.path_label, c.path, c.category_name, c.printer_role].join(' '));

        const form = document.getElementById('catForm');
        if(shouldScroll !== false && form) form.scrollIntoView({behavior:'smooth', block:'start'});
    }

    const byParent = {};
    categories.forEach(c => {
        const pid = parseInt(c.parent_id || 0, 10) || 0;
        if(!byParent[pid]) byParent[pid] = [];
        byParent[pid].push(c);
    });

    let currentParent = 0;
    let breadcrumbStack = [{id:0, label:'Root'}];
    const catDrill = document.getElementById('categoryDrill');
    const itemDrill = document.getElementById('itemDrill');
    const posBreadcrumb = document.getElementById('posBreadcrumb');
    const menuSearch = document.getElementById('menuSearch');

    function renderDrill(parentId){
        currentParent = parseInt(parentId || 0, 10) || 0;
        const term = menuSearch ? menuSearch.value.trim().toLowerCase() : '';
        if(posBreadcrumb){
            posBreadcrumb.innerHTML = breadcrumbStack.map((b, idx) => '<button type="button" class="btn btn-link btn-sm p-0 crumb" data-idx="'+idx+'">'+escapeHtml(b.label)+'</button>').join(' &gt; ');
        }

        if(catDrill){
            catDrill.innerHTML = '';
            const cats = term ? categories.filter(c => String(c.path_label || c.category_name || '').toLowerCase().includes(term)) : (byParent[currentParent] || []);
            cats.forEach(c => {
                const wrap = document.createElement('div');
                wrap.className = 'drill-card-wrap';

                const btn = document.createElement('button');
                btn.type = 'button';
                btn.className = 'drill-btn';
                btn.dataset.id = c.id;
                btn.style.background = buttonBg(c.button_color, [c.path_label, c.path, c.category_name, c.printer_role].join(' '));
                btn.innerHTML = '<strong><i class="bi bi-folder2-open me-1"></i>'+escapeHtml(c.category_name || '')+'</strong><span>'+escapeHtml(c.path_label || c.path || '')+'</span><span class="small opacity-75">Click to open</span>';
                btn.addEventListener('click', () => {
                    breadcrumbStack.push({id:parseInt(c.id,10), label:c.category_name || 'Category'});
                    renderDrill(parseInt(c.id,10));
                });

                const editBtn = document.createElement('button');
                editBtn.type = 'button';
                editBtn.className = 'drill-edit-btn';
                editBtn.title = 'Edit this root/subroot/category';
                editBtn.innerHTML = '<i class="bi bi-pencil-square"></i>';
                editBtn.addEventListener('click', (ev) => {
                    ev.preventDefault();
                    ev.stopPropagation();
                    editCategoryObject(c, true);
                });

                wrap.appendChild(btn);
                wrap.appendChild(editBtn);
                catDrill.appendChild(wrap);
            });
        }

        if(itemDrill){
            itemDrill.innerHTML = '';
            const showItems = items.filter(it => {
                if(parseInt(it.is_active || 1, 10) !== 1) return false;
                const text = [it.item_name, it.item_code, it.description, it.tags, it.category_path, it.category_name].join(' ').toLowerCase();
                if(term) return text.includes(term);
                return parseInt(it.category_id || 0, 10) === currentParent;
            });
            showItems.forEach(it => {
                const btn = document.createElement('button');
                btn.type = 'button';
                btn.className = 'item-btn';
                const cat = categoryById(it.category_id);
                btn.style.background = buttonBg(it.button_color || (cat ? cat.button_color : ''), [it.category_path, it.category_name, it.item_name, it.tags, it.printer_role].join(' '));
                const tags = String(it.tags || '').split(',').map(x => x.trim()).filter(Boolean).map(x => '<span class="tag-pill">'+escapeHtml(x)+'</span>').join('');
                btn.innerHTML = '<strong><i class="bi bi-check2-square me-1"></i>'+escapeHtml(it.item_name || '')+'</strong><span>'+escapeHtml(it.category_path || it.category_name || '')+'</span><span>'+money(it.price || 0)+'</span><div>'+tags+'</div>';
                btn.addEventListener('click', () => editItem(it));
                itemDrill.appendChild(btn);
            });
            if(!showItems.length){
                itemDrill.innerHTML = '<div class="text-muted small">No items at this level. Drill down, search, or attach an item to this category.</div>';
            }
        }
    }

    document.addEventListener('click', function(e){
        const crumb = e.target.closest('.crumb');
        if(crumb){
            const idx = parseInt(crumb.dataset.idx || '0', 10) || 0;
            breadcrumbStack = breadcrumbStack.slice(0, idx + 1);
            renderDrill(breadcrumbStack[idx].id);
        }
        const toggle = e.target.closest('.tree-toggle');
        if(toggle){
            const el = document.getElementById(toggle.dataset.target || '');
            if(el){
                const open = el.style.display !== 'none';
                el.style.display = open ? 'none' : '';
                const icon = toggle.querySelector('i');
                if(icon) icon.className = open ? 'bi bi-chevron-right' : 'bi bi-chevron-down';
            }
        }
        const cat = e.target.closest('.select-cat');
        if(cat){
            const obj = categoryById(cat.dataset.id) || {
                id: cat.dataset.id || '',
                category_name: cat.dataset.name || '',
                parent_id: cat.dataset.parent || 0,
                printer_role: cat.dataset.role || 'kitchen',
                button_color: cat.dataset.color || '',
                sort_order: cat.dataset.sort || 1,
                is_active: cat.dataset.active || 1,
                path_label: cat.dataset.path || ''
            };
            editCategoryObject(obj, true);
        }
    });

    let draggedCategoryId = 0;

    function isDescendantCategory(parentId, maybeChildId){
        parentId = parseInt(parentId || 0, 10) || 0;
        maybeChildId = parseInt(maybeChildId || 0, 10) || 0;
        if(parentId <= 0 || maybeChildId <= 0) return false;
        let cursor = categoryById(maybeChildId);
        let guard = 0;
        while(cursor && guard++ < 100){
            const pid = parseInt(cursor.parent_id || 0, 10) || 0;
            if(pid === parentId) return true;
            cursor = categoryById(pid);
        }
        return false;
    }

    function submitCategoryMove(categoryId, newParentId){
        categoryId = parseInt(categoryId || 0, 10) || 0;
        newParentId = parseInt(newParentId || 0, 10) || 0;
        if(categoryId <= 0) return;
        if(categoryId === newParentId){ alert('You cannot move a category into itself.'); return; }
        if(isDescendantCategory(categoryId, newParentId)){
            alert('You cannot move a category inside one of its own subcategories.');
            return;
        }
        const moved = categoryById(categoryId);
        const target = newParentId > 0 ? categoryById(newParentId) : null;
        const msg = 'Move "' + (moved ? moved.category_name : ('#' + categoryId)) + '" under ' + (target ? ('"' + target.category_name + '"') : 'Root') + '?';
        if(!confirm(msg)) return;
        const form = document.getElementById('dragCategoryForm');
        const idField = document.getElementById('drag_category_id');
        const parentField = document.getElementById('drag_new_parent_id');
        if(!form || !idField || !parentField) return;
        idField.value = String(categoryId);
        parentField.value = String(newParentId);
        form.submit();
    }

    document.querySelectorAll('.menu-tree-node[draggable="true"]').forEach(node => {
        node.addEventListener('dragstart', function(e){
            draggedCategoryId = parseInt(this.dataset.id || 0, 10) || 0;
            this.classList.add('dragging');
            if(e.dataTransfer){
                e.dataTransfer.effectAllowed = 'move';
                e.dataTransfer.setData('text/plain', String(draggedCategoryId));
            }
        });
        node.addEventListener('dragend', function(){
            this.classList.remove('dragging');
            document.querySelectorAll('.drag-over').forEach(el => el.classList.remove('drag-over'));
            draggedCategoryId = 0;
        });
    });

    document.querySelectorAll('.menu-tree-row[data-drop-id], #rootDropZone').forEach(zone => {
        zone.addEventListener('dragover', function(e){
            if(!draggedCategoryId) return;
            const targetId = parseInt(this.dataset.dropId || 0, 10) || 0;
            if(targetId === draggedCategoryId || isDescendantCategory(draggedCategoryId, targetId)) return;
            e.preventDefault();
            if(e.dataTransfer) e.dataTransfer.dropEffect = 'move';
            this.classList.add('drag-over');
        });
        zone.addEventListener('dragleave', function(){ this.classList.remove('drag-over'); });
        zone.addEventListener('drop', function(e){
            if(!draggedCategoryId) return;
            e.preventDefault();
            this.classList.remove('drag-over');
            const targetId = parseInt(this.dataset.dropId || 0, 10) || 0;
            submitCategoryMove(draggedCategoryId, targetId);
        });
    });

    function selectedModifierGroupIds(){
        const sel = document.getElementById('item_modifier_groups');
        if(!sel) return [];
        return [...sel.options].filter(o => o.selected).map(o => parseInt(o.value || 0, 10)).filter(Boolean);
    }

    function currentModifierGroupOrder(){
        const hidden = document.getElementById('item_modifier_group_order');
        const existing = hidden && hidden.value ? hidden.value.split(',').map(x => parseInt(x || 0, 10)).filter(Boolean) : [];
        const selected = selectedModifierGroupIds();
        const selectedSet = new Set(selected);
        const ordered = existing.filter(id => selectedSet.has(id));
        selected.forEach(id => { if(!ordered.includes(id)) ordered.push(id); });
        return ordered;
    }

    function setModifierGroupOrder(order){
        const sel = document.getElementById('item_modifier_groups');
        const hidden = document.getElementById('item_modifier_group_order');
        if(!sel || !hidden) return;
        const selected = selectedModifierGroupIds();
        const selectedSet = new Set(selected);
        const clean = (order || []).map(x => parseInt(x || 0, 10)).filter(id => selectedSet.has(id));
        selected.forEach(id => { if(!clean.includes(id)) clean.push(id); });
        hidden.value = clean.join(',');
        renderModifierGroupOrder();
    }

    function modifierGroupLabelFromOption(opt){
        if(!opt) return 'Modifier Group';
        const max = parseInt(opt.dataset.max || 0, 10) === 0 ? '∞' : (opt.dataset.max || '1');
        return {
            name: opt.dataset.name || opt.textContent.trim(),
            meta: (opt.dataset.type || 'optional') + ' • ' + (opt.dataset.min || '0') + '-' + max
        };
    }

    function renderModifierGroupOrder(){
        const sel = document.getElementById('item_modifier_groups');
        const panel = document.getElementById('selectedModifierGroupOrder');
        const hidden = document.getElementById('item_modifier_group_order');
        if(!sel || !panel || !hidden) return;
        const selected = selectedModifierGroupIds();
        const selectedSet = new Set(selected);
        let order = hidden.value ? hidden.value.split(',').map(x => parseInt(x || 0, 10)).filter(id => selectedSet.has(id)) : [];
        selected.forEach(id => { if(!order.includes(id)) order.push(id); });
        hidden.value = order.join(',');
        if(!order.length){
            panel.innerHTML = '<div class="text-muted small">Select modifier groups above to build the prompt order.</div>';
            return;
        }
        panel.innerHTML = order.map((id, idx) => {
            const opt = [...sel.options].find(o => parseInt(o.value || 0, 10) === id);
            const label = modifierGroupLabelFromOption(opt);
            return '<div class="selected-group-row" data-group-id="'+id+'">'
                + '<div class="selected-group-main"><span class="group-seq-no">'+(idx+1)+'</span><div class="min-w-0"><div class="selected-group-title">'+escapeHtml(label.name)+'</div><div class="selected-group-meta">'+escapeHtml(label.meta)+'</div></div></div>'
                + '<div class="selected-group-actions">'
                + '<button type="button" class="btn btn-light border move-item-group-up" title="Move up" '+(idx===0?'disabled':'')+'><i class="bi bi-arrow-up"></i></button>'
                + '<button type="button" class="btn btn-light border move-item-group-down" title="Move down" '+(idx===order.length-1?'disabled':'')+'><i class="bi bi-arrow-down"></i></button>'
                + '<button type="button" class="btn btn-outline-danger remove-item-group" title="Remove"><i class="bi bi-x-lg"></i></button>'
                + '</div></div>';
        }).join('');
        panel.querySelectorAll('.move-item-group-up').forEach(btn => btn.addEventListener('click', function(){
            const id = parseInt(this.closest('.selected-group-row').dataset.groupId || 0, 10);
            const i = order.indexOf(id); if(i > 0){ [order[i-1], order[i]] = [order[i], order[i-1]]; setModifierGroupOrder(order); }
        }));
        panel.querySelectorAll('.move-item-group-down').forEach(btn => btn.addEventListener('click', function(){
            const id = parseInt(this.closest('.selected-group-row').dataset.groupId || 0, 10);
            const i = order.indexOf(id); if(i >= 0 && i < order.length-1){ [order[i], order[i+1]] = [order[i+1], order[i]]; setModifierGroupOrder(order); }
        }));
        panel.querySelectorAll('.remove-item-group').forEach(btn => btn.addEventListener('click', function(){
            const id = parseInt(this.closest('.selected-group-row').dataset.groupId || 0, 10);
            const opt = [...sel.options].find(o => parseInt(o.value || 0, 10) === id);
            if(opt) opt.selected = false;
            setModifierGroupOrder(order.filter(x => x !== id));
        }));
    }

    function updateInventoryLinkControls(){
        const itemIdInput = document.getElementById('item_id');
        const invSelect = document.getElementById('item_inv');
        const delinkBtn = document.getElementById('item_delink_inventory');
        const status = document.getElementById('itemInventoryLinkStatus');
        if (!invSelect || !delinkBtn || !status) return;

        let inventoryId = 0;
        if (invSelect.tomselect) {
            inventoryId = parseInt(invSelect.tomselect.getValue() || 0, 10);
        } else {
            inventoryId = parseInt(invSelect.value || 0, 10);
        }
        const menuItemId = itemIdInput ? parseInt(itemIdInput.value || 0, 10) : 0;

        if (menuItemId > 0 && inventoryId > 0) {
            delinkBtn.style.display = '';
            status.innerHTML = '<span class="text-success fw-bold">Linked to inventory item #' + inventoryId + '.</span> Delinking will not delete the menu item or its sales history.';
        } else {
            delinkBtn.style.display = 'none';
            status.textContent = inventoryId > 0
                ? 'This inventory item will be linked when you save the menu item.'
                : 'Not linked. The menu item can still be sold, but no direct linked-item stock deduction will occur.';
        }
    }

    function editItem(x){
        item_id.value = x.id || '';
        item_cat.value = x.category_id || '';
        item_name.value = x.item_name || '';
        item_price.value = x.price || 0;
        item_tax.value = x.tax_rate || 0;
        item_role.value = x.printer_role || 'kitchen';
        item_food.value = x.is_food || 0;
        item_bar.value = x.is_bar || 0;
        if (item_inv.tomselect) { item_inv.tomselect.setValue(x.inventory_item_id || 0, true); }
        else { item_inv.value = x.inventory_item_id || 0; }
        item_code.value = x.item_code || '';
        item_desc.value = x.description || '';
        item_sort.value = x.sort_order || 1;
        item_active.value = x.is_active || 1;
        item_tags.value = x.tags || '';
        item_color.value = x.button_color || '';
        updateColorPreview(item_color, document.getElementById('itemColorPreview'), [x.category_path, x.category_name, x.item_name, x.tags, x.printer_role].join(' '));
        item_selectable.value = x.is_selectable || 1;
        [...item_modifiers.options].forEach(opt => opt.selected = (x._modifier_ids || []).map(Number).includes(parseInt(opt.value,10)));
        if(typeof item_modifier_groups !== 'undefined') {
            const groupIds = (x._modifier_group_ids || []).map(Number);
            [...item_modifier_groups.options].forEach(opt => opt.selected = groupIds.includes(parseInt(opt.value,10)));
            const hidden = document.getElementById('item_modifier_group_order');
            if(hidden) hidden.value = groupIds.join(',');
            renderModifierGroupOrder();
        }
        updateItemBreadcrumb();
        updateInventoryLinkControls();
        const editorCard = document.getElementById('item-editor-card');
        if (editorCard) {
            editorCard.scrollIntoView({behavior:'smooth', block:'start'});
            editorCard.classList.remove('elite-panel-highlight');
            void editorCard.offsetWidth;
            editorCard.classList.add('elite-panel-highlight');
        }
    }

    const delinkInventoryButton = document.getElementById('item_delink_inventory');
    if (delinkInventoryButton) {
        delinkInventoryButton.addEventListener('click', function(){
            const menuItemId = parseInt((document.getElementById('item_id') || {}).value || 0, 10);
            if (menuItemId <= 0) {
                alert('Save the menu item first before delinking inventory.');
                return;
            }
            if (!confirm('Remove this inventory link? The menu item will remain sellable, but direct linked-item stock deduction will stop until another inventory item is linked.')) {
                return;
            }
            document.getElementById('delink_inventory_item_id').value = menuItemId;
            document.getElementById('delinkInventoryForm').submit();
        });
    }

    if (typeof item_inv !== 'undefined' && item_inv) {
        item_inv.addEventListener('change', updateInventoryLinkControls);
    }

    document.querySelectorAll('.edit-item').forEach(b => b.addEventListener('click', function(){ editItem(JSON.parse(this.dataset.json)); }));

    updateInventoryLinkControls();

    function updateItemBreadcrumb(){
        const opt = item_cat.options[item_cat.selectedIndex];
        const txt = opt && opt.dataset.path ? opt.dataset.path : 'Attach items at any category depth.';
        document.getElementById('itemBreadcrumb').textContent = txt;
        if(opt && opt.dataset.role) item_role.value = opt.dataset.role;
        if(opt && opt.dataset.color && !item_color.value.trim()) item_color.value = opt.dataset.color;
        updateColorPreview(item_color, document.getElementById('itemColorPreview'), [txt, item_name.value, item_role.value].join(' '));
    }
    function updateCatBreadcrumb(){
        const opt = cat_parent_id.options[cat_parent_id.selectedIndex];
        const parentText = opt && opt.value !== '0' ? opt.textContent.replace(/—/g,'').trim() : '';
        const name = cat_name.value.trim();
        cat_breadcrumb.value = parentText ? (parentText + ' > ' + (name || 'New Category')) : (name || 'Root category');
        updateColorPreview(cat_color, document.getElementById('catColorPreview'), cat_breadcrumb.value + ' ' + cat_role.value);
    }

    document.getElementById('item_cat')?.addEventListener('change', updateItemBreadcrumb);
    document.getElementById('cat_parent_id')?.addEventListener('change', updateCatBreadcrumb);
    document.getElementById('cat_name')?.addEventListener('input', updateCatBreadcrumb);
    document.getElementById('newCategoryBtn')?.addEventListener('click', function(){
        catForm.reset();
        cat_id.value='';
        disableInvalidParentOptions(0);
        cat_parent_id.value='0';
        cat_role.value='kitchen';
        cat_color.value='';
        cat_sort.value='1';
        cat_active.value='1';
        updateCatBreadcrumb();
        catForm.scrollIntoView({behavior:'smooth', block:'start'});
    });
    document.getElementById('clearItemBtn')?.addEventListener('click', function(){ itemForm.reset(); item_id.value=''; if(item_inv && item_inv.tomselect){ item_inv.tomselect.setValue(0, true); } [...item_modifiers.options].forEach(o=>o.selected=false); if(typeof item_modifier_groups !== 'undefined') [...item_modifier_groups.options].forEach(o=>o.selected=false); const hidden=document.getElementById('item_modifier_group_order'); if(hidden) hidden.value=''; renderModifierGroupOrder(); updateItemBreadcrumb(); });
    document.getElementById('item_modifier_groups')?.addEventListener('change', function(){ setModifierGroupOrder(currentModifierGroupOrder()); });
    document.getElementById('sortGroupsBySetupBtn')?.addEventListener('click', function(){
        const selected = selectedModifierGroupIds();
        const sel = document.getElementById('item_modifier_groups');
        const ordered = selected.slice().sort((a,b) => {
            const oa = [...sel.options].find(o => parseInt(o.value||0,10)===a);
            const ob = [...sel.options].find(o => parseInt(o.value||0,10)===b);
            const sa = parseInt(oa?.dataset.sort || 9999, 10);
            const sb = parseInt(ob?.dataset.sort || 9999, 10);
            return sa === sb ? String(oa?.dataset.name||'').localeCompare(String(ob?.dataset.name||'')) : sa - sb;
        });
        setModifierGroupOrder(ordered);
    });

    function modifierBadgeClass(type){
        type = String(type || '').toLowerCase();
        if(type === 'required') return 'danger';
        if(type === 'default') return 'success';
        return 'secondary';
    }

    function groupOptions(groupId){
        groupId = parseInt(groupId || 0, 10) || 0;
        return modifierOptions.filter(m => {
            const legacyGroup = parseInt(m.modifier_group_id || 0, 10) || 0;
            const linked = Array.isArray(m._linked_group_ids) ? m._linked_group_ids.map(x => parseInt(x || 0, 10) || 0) : [];
            return legacyGroup === groupId || linked.includes(groupId);
        });
    }

    function editModifierOption(m){
        mod_option_id.value = m.id || '';
        mod_option_group.value = m.modifier_group_id || '';
        filterParentOptions(m.modifier_group_id || 0, m.id || 0);
        mod_option_parent.value = m.parent_modifier_id || 0;
        mod_option_name.value = m.modifier_name || '';
        mod_option_price.value = m.price_delta || 0;
        mod_option_prefix.value = m.prefix_allowed || 1;
        mod_option_sort.value = m.sort_order || 1;
        mod_option_active.value = m.is_active || 1;
        document.getElementById('modifierOptionForm')?.scrollIntoView({behavior:'smooth', block:'start'});
    }

    function filterParentOptions(groupId, currentId){
        groupId = parseInt(groupId || 0, 10) || 0;
        currentId = parseInt(currentId || 0, 10) || 0;
        [...mod_option_parent.options].forEach(opt => {
            if(opt.value === '0') { opt.hidden = false; return; }
            const optGroup = parseInt(opt.dataset.group || 0, 10) || 0;
            const optId = parseInt(opt.value || 0, 10) || 0;
            opt.hidden = (groupId > 0 && optGroup !== groupId) || (currentId > 0 && optId === currentId);
        });
        if(mod_option_parent.selectedOptions[0]?.hidden) mod_option_parent.value = '0';
    }

    function renderModifierGroupDetail(groupId){
        groupId = parseInt(groupId || 0, 10) || 0;
        const panel = document.getElementById('modifierGroupDetailPanel');
        if(!panel) return;
        const group = modifierGroups.find(g => parseInt(g.id || 0, 10) === groupId);
        if(!group){
            panel.innerHTML = '<div class="modifier-detail-empty"><i class="bi bi-hand-index-thumb"></i><strong>Click a modifier group above</strong><span>All options in that group will show here in a clean nested view.</span></div>';
            return;
        }
        const options = groupOptions(groupId);
        const parents = options.filter(m => !parseInt(m.parent_modifier_id || 0, 10));
        const childMap = {};
        options.forEach(m => {
            const pid = parseInt(m.parent_modifier_id || 0, 10) || 0;
            if(pid > 0){ if(!childMap[pid]) childMap[pid] = []; childMap[pid].push(m); }
        });
        const orphanChildren = options.filter(m => parseInt(m.parent_modifier_id || 0, 10) > 0 && !options.find(x => parseInt(x.id||0,10) === parseInt(m.parent_modifier_id||0,10)));
        const top = parents.length ? parents : orphanChildren;
        const badge = modifierBadgeClass(group.group_type);
        const maxTxt = parseInt(group.max_select || 0, 10) === 0 ? '∞' : String(group.max_select || 1);
        let html = '<div class="modifier-detail-head">'
            + '<div><div class="modifier-detail-title">'+escapeHtml(group.group_name || 'Modifier Group')+'</div>'
            + '<div class="modifier-detail-meta"><span class="badge text-bg-'+badge+'">'+escapeHtml(String(group.group_type || 'optional'))+'</span><span class="badge text-bg-light border">Min '+escapeHtml(group.min_select || 0)+'</span><span class="badge text-bg-light border">Max '+escapeHtml(maxTxt)+'</span><span class="badge text-bg-primary">'+options.length+' option(s)</span></div></div>'
            + '<div class="modifier-detail-actions"><button type="button" class="btn btn-sm btn-primary" id="addOptionToSelectedGroup"><i class="bi bi-plus-circle me-1"></i>Add Option</button></div>'
            + '</div>'
            + '<input type="text" class="form-control form-control-sm modifier-search-mini" id="modifierOptionSearch" placeholder="Search options inside '+escapeHtml(group.group_name || 'group')+'...">'
            + '<div class="modifier-tree" id="modifierTree">';
        if(!options.length){
            html += '<div class="alert alert-light border mb-0 small">No options yet. Use <strong>Add Option</strong> to start adding options under this group.</div>';
        }else{
            top.forEach(parent => {
                const kids = childMap[parseInt(parent.id || 0, 10)] || [];
                const price = parseFloat(parent.price_delta || 0);
                html += '<div class="modifier-parent-card" data-search="'+escapeHtml([parent.modifier_name, price].join(' ').toLowerCase())+'">'
                    + '<div class="modifier-parent-line"><button type="button" class="btn btn-sm btn-link p-0 text-start edit-mod-option-inline" data-id="'+parseInt(parent.id||0,10)+'"><span class="modifier-parent-name">'+escapeHtml(parent.modifier_name || '')+'</span></button>'
                    + (price !== 0 ? '<span class="modifier-price-pill">'+money(price)+'</span>' : '<span class="badge text-bg-light border">No charge</span>') + '</div>';
                if(kids.length){
                    html += '<div class="modifier-child-wrap">';
                    kids.forEach(k => {
                        const kp = parseFloat(k.price_delta || 0);
                        html += '<button type="button" class="modifier-child-chip edit-mod-option-inline" data-id="'+parseInt(k.id||0,10)+'"><span>↳ '+escapeHtml(k.modifier_name || '')+'</span>'+(kp !== 0 ? '<em>'+money(kp)+'</em>' : '')+'</button>';
                    });
                    html += '</div>';
                }
                html += '</div>';
            });
        }
        html += '</div>';
        panel.innerHTML = html;
        document.querySelectorAll('.modifier-group-card').forEach(x => x.classList.toggle('active', parseInt(x.dataset.groupId||0,10) === groupId));
        document.getElementById('addOptionToSelectedGroup')?.addEventListener('click', function(){
            modifierOptionForm.reset();
            mod_option_id.value = '';
            mod_option_group.value = groupId;
            filterParentOptions(groupId, 0);
            mod_option_parent.value = '0';
            mod_option_name.focus();
        });
        document.querySelectorAll('.edit-mod-option-inline').forEach(btn => btn.addEventListener('click', function(){
            const id = parseInt(this.dataset.id || 0, 10) || 0;
            const m = modifierOptions.find(x => parseInt(x.id || 0, 10) === id);
            if(m) editModifierOption(m);
        }));
        document.getElementById('modifierOptionSearch')?.addEventListener('input', function(){
            const term = this.value.trim().toLowerCase();
            document.querySelectorAll('#modifierTree .modifier-parent-card').forEach(card => {
                const text = card.textContent.toLowerCase();
                card.classList.toggle('hidden-by-search', term && !text.includes(term));
            });
        });
    }

    function editModifierGroup(g){
        mod_group_id.value = g.id || '';
        mod_group_name.value = g.group_name || '';
        mod_group_type.value = g.group_type || 'optional';
        mod_group_min.value = g.min_select || 0;
        mod_group_max.value = g.max_select || 1;
        mod_group_sort.value = g.sort_order || 1;
        mod_group_active.value = g.is_active || 1;
        if (typeof mod_group_linked_modifiers !== 'undefined') {
            const linked = Array.isArray(g._linked_modifier_ids) ? g._linked_modifier_ids.map(x => parseInt(x || 0, 10)) : [];
            [...mod_group_linked_modifiers.options].forEach(o => { o.selected = linked.includes(parseInt(o.value || 0, 10)); });
        }
        mod_option_group.value = g.id || '';
        filterParentOptions(g.id || 0, 0);
        renderModifierGroupDetail(g.id || 0);
    }

    document.querySelectorAll('.edit-mod-group').forEach(b => {
        b.addEventListener('click', function(e){
            if (e.target.closest('form') || e.target.closest('button[type=submit]')) return;
            const g = JSON.parse(this.dataset.json || '{}');
            editModifierGroup(g);
        });
        b.addEventListener('keydown', function(e){
            if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                const g = JSON.parse(this.dataset.json || '{}');
                editModifierGroup(g);
            }
        });
    });
    document.querySelectorAll('.focus-modifier-group').forEach(b => b.addEventListener('click', function(){ renderModifierGroupDetail(this.dataset.groupId || 0); }));
    document.getElementById('modifierGroupSearch')?.addEventListener('input', function(){
        const term = this.value.trim().toLowerCase();
        document.querySelectorAll('.modifier-group-card').forEach(card => {
            const text = String(card.dataset.searchText || card.textContent || '').toLowerCase();
            card.classList.toggle('hidden-by-search', term && !text.includes(term));
        });
        document.querySelectorAll('.modifier-option-group-block').forEach(block => {
            const text = block.textContent.toLowerCase();
            block.classList.toggle('hidden-by-search', term && !text.includes(term));
        });
    });
    document.getElementById('showAllModifierGroupsBtn')?.addEventListener('click', function(){
        const input = document.getElementById('modifierGroupSearch');
        if(input) input.value = '';
        document.querySelectorAll('.hidden-by-search').forEach(x => x.classList.remove('hidden-by-search'));
    });
    document.getElementById('clearModifierGroupBtn')?.addEventListener('click', function(){ modifierGroupForm.reset(); mod_group_id.value=''; if (typeof mod_group_linked_modifiers !== 'undefined') [...mod_group_linked_modifiers.options].forEach(o=>o.selected=false); renderModifierGroupDetail(0); });
    document.getElementById('mod_option_group')?.addEventListener('change', function(){ filterParentOptions(this.value, mod_option_id.value); renderModifierGroupDetail(this.value); });
    document.querySelectorAll('.edit-mod-option').forEach(b => b.addEventListener('click', function(){
        const m = JSON.parse(this.dataset.json || '{}');
        editModifierOption(m);
    }));
    document.getElementById('clearModifierOptionBtn')?.addEventListener('click', function(){ modifierOptionForm.reset(); mod_option_id.value=''; filterParentOptions(0,0); });
    document.getElementById('item_inv')?.addEventListener('change', function(){ const opt=this.options[this.selectedIndex]; if(opt && parseFloat(opt.dataset.price||0)>0 && !parseFloat(item_price.value||0)) item_price.value=parseFloat(opt.dataset.price).toFixed(2); });
    // Turn the (now full, possibly thousands-long) linked inventory list into a
    // searchable dropdown. Falls back to a plain <select> if the library is absent.
    (function(){
        const invEl = document.getElementById('item_inv');
        if (invEl && typeof TomSelect !== 'undefined' && !invEl.tomselect) {
            new TomSelect(invEl, {
                maxOptions: null,          // show all matches, no cap
                sortField: { field: 'text', direction: 'asc' },
                placeholder: 'Search inventory item...',
                allowEmptyOption: true,
                dropdownParent: 'body'     // avoid clipping inside modal/scroll panels
            });
        }
    })();
    menuSearch?.addEventListener('input', () => renderDrill(currentParent));

    function updateColorPreview(input, preview, fallbackText){ if(preview && input){ preview.style.background = buttonBg(input.value, fallbackText || ''); } }
    document.getElementById('item_color')?.addEventListener('input', function(){ updateColorPreview(this, document.getElementById('itemColorPreview'), itemBreadcrumb.textContent + ' ' + item_name.value); });
    document.getElementById('cat_color')?.addEventListener('input', function(){ updateColorPreview(this, document.getElementById('catColorPreview'), cat_breadcrumb.value + ' ' + cat_role.value); });

    function escapeHtml(s){ return String(s ?? '').replace(/[&<>'"]/g, ch => ({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[ch])); }
    function money(v){ return parseFloat(v || 0).toFixed(2); }
    renderModifierGroupOrder();
    updateCatBreadcrumb();
    updateItemBreadcrumb();
    renderDrill(0);
});
</script>
<?php require_once __DIR__ . '/../../includes/footer.php'; ?>
