<?php
// Enable verbose PHP error output for development
@ini_set('display_errors', '1');
@ini_set('display_startup_errors', '1');
error_reporting(E_ALL);


define('BEEZUI_NAV_WIDTH', '60');

// Session-backed system mode component using HTMX
if (empty($_SESSION)) {

    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
}

// Define project root constant if not already defined
if (!defined('BEEZUI_ROOT')) {
    define('BEEZUI_ROOT', __DIR__);
}

// Bootstrap core early so we can serve partials for HTMX
require_once BEEZUI_ROOT . '/components/bootstrap.php';

$tabParam = \Components\Router::tabParam();
$subtabParam = \Components\Router::subtabParam();
$pageParam = \Components\Router::pageParam();

// Detect partial request (HTMX or explicit flag)
$isPartial = (\Components\Support\Htmx::isRequest()) || (mh_get('partial', 0, 'int') == 1);

// Determine requested route name based on context
$routeName = null;
if ($isPartial) {
    $routeName = mh_get($pageParam, null, 'string');
    if ($routeName === null) {
        // Fallback for callers that still send the tab param
        $routeName = mh_get($tabParam, null, 'string');
    }
} else {
    $routeName = mh_get($tabParam, null, 'string');
    if ($routeName === null) {
        // Fallback for callers that only sent the page param
        $routeName = mh_get($pageParam, null, 'string');
    }
}
$routeName = $routeName ? preg_replace('/[^_a-z]/', '', strtolower((string)$routeName)) : 'dashboard';
$tab = $routeName;

// Resolve path from route name
$path = \Components\Router::path($routeName);
if (!$path) {
    // Fallback to conventional pages/<route>.php
    $candidate = 'pages/' . $routeName . '.php';
    $path = is_file(BEEZUI_ROOT . '/' . $candidate) ? $candidate : null;
}

// If this is an HTMX request (or explicit partial), capture and optimize the partial HTML (inline <svg> → CSS)
if ($isPartial) {
    if ($path && is_file(BEEZUI_ROOT . '/' . $path)) {

        // Start SVG optimizer buffering so we can transform the partial output
        $svgOpt = \Components\SvgCssOptimizer::begin([
                'cache_dir' => BEEZUI_ROOT . '/public/cache',
                'web_path' => (defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : '') . 'public/cache',
                'base64' => false,
                'class_prefix' => 'svg-',
                'size_var' => '--svg-size',
        ]);

        include BEEZUI_ROOT . '/' . $path;

        // Flush transformed content (injects a cache-busted CSS link for the found icons)
        $svgOpt->flush();
        exit;
    } else {
        http_response_code(404);
        echo 'Not found';
        exit;
    }
}
?>
<!DOCTYPE html>
<html class="h-full group/collapse" lang="<?= mh_session('language_code', 'en') ?>">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>MailBeez Admin</title>
    <!-- Dark mode bootstrap: prevent FOUC by setting class on <html> ASAP -->
    <script>
        try {
            if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
                // document.documentElement.classList.add('dark');
            } else {
                document.documentElement.classList.remove('dark');
            }
            document.documentElement.classList.remove('dark');
        } catch (e) {
            // no-op
        }
    </script>
    <script>
        // Apply persisted UI density asap to avoid FOUC
        try {
            var savedDensity = localStorage.getItem('ui-density') || 'normal';
            var htmlEl = document.documentElement;
            htmlEl.classList.remove('density-compact', 'density-very-compact');
            if (savedDensity === 'compact') htmlEl.classList.add('density-compact');
            else if (savedDensity === 'very-compact') htmlEl.classList.add('density-very-compact');
        } catch (e) { /* no-op */
        }
    </script>
    <!--    <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />-->
    <link rel="stylesheet"
          href="<?php echo defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : ''; ?>appui/assets/css/tailwind.output.css"/>
    <!-- Flag Icons for language flags in i18n fields: https://flagicons.lipis.dev/ -->
    <link rel="stylesheet"
          href="<?php echo defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : ''; ?>appui/assets/css/flag-icons.min.css"/>

    <meta name="htmx-config" content='{"scrollBehavior":"smooth"}'>

    <script>
        window.APP_LOCALE = '<?php echo htmlspecialchars(mh_session('language_code', 'en'), ENT_QUOTES); ?>';
    </script>

    <script defer
            src="<?php echo defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : ''; ?>appui/assets/js/htmx.min.js?ver=<?= mh_cfg('MAILBEEZ_VERSION') ?>"></script>
    <!--    <script defer src="-->
    <?php //echo defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : ''; ?><!--appui/assets/js/preload.min.js?ver=-->
    <?php //= mh_cfg('MAILBEEZ_VERSION') ?><!--"></script>-->
    <script src="<?php echo defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : ''; ?>appui/assets/js/mb-loader.js?ver=<?= mh_cfg('MAILBEEZ_VERSION') ?>"></script>
    <script src="<?php echo defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : ''; ?>appui/assets/js/mb-modal.js?ver=<?= mh_cfg('MAILBEEZ_VERSION') ?>"></script>
    <script defer
            src="<?php echo defined('BEEZUI_WEB_ROOT') ? BEEZUI_WEB_ROOT : ''; ?>public/js/app.js?ver=<?= mh_cfg('MAILBEEZ_VERSION') ?>"></script>

    <style>[x-cloak] {
            display: none !important;
        }</style>
    <script>
        // Global lightweight Alpine validation helper for forms rendered by Engine
        // Usage: Object.assign(existingXData, MBForm.validator(schema))
        window.MBForm = window.MBForm || {};
        window.MBForm.validator = function (schema) {
            return {
                schema: schema || {},
                clientErrors: {},
                _getVal(name) {
                    let v = this.form ? this.form[name] : undefined;
                    if (v === undefined || v === null) return '';
                    if (typeof v === 'boolean') return v ? 'on' : '';
                    return v;
                },
                _isIntString(s) {
                    return /^-?\d+$/.test(String(s));
                },
                _parseDateToTs(val) {
                    if (val === undefined || val === null) return null;
                    const s = String(val).trim();
                    if (!s) return null;
                    if (/^\d{4}-\d{2}-\d{2}$/.test(s)) {
                        const d = new Date(s + 'T00:00:00');
                        if (!isNaN(d)) return Math.floor(d.getTime() / 1000);
                    }
                    const t = Date.parse(s);
                    if (!isNaN(t)) return Math.floor(t / 1000);
                    return null;
                },
                validateField(name) {
                    const r = this.schema[name];
                    const el = this.$root && this.$root.querySelector ? this.$root.querySelector('[name="' + (window.CSS && CSS.escape ? CSS.escape(name) : name) + '"]') : null;
                    if (!el) {
                        this.clientErrors[name] = [];
                        return true;
                    }
                    const v = this._getVal(name);
                    const errs = [];
                    if (!r) {
                        this.clientErrors[name] = [];
                        return true;
                    }
                    if (r.required && String(v).trim() === '') {
                        errs.push('This field is required.');
                    }
                    if (r.type === 'integer' && String(v).trim() !== '') {
                        if (!this._isIntString(v)) {
                            errs.push('Please enter a valid integer.');
                        }
                        const num = parseInt(v, 10);
                        if (r.min !== undefined && this._isIntString(r.min) && num < parseInt(r.min, 10)) {
                            errs.push('Minimum value is ' + r.min + '.');
                        }
                        if (r.max !== undefined && this._isIntString(r.max) && num > parseInt(r.max, 10)) {
                            errs.push('Maximum value is ' + r.max + '.');
                        }
                    }
                    if (Array.isArray(r.compare)) {
                        for (const cmp of r.compare) {
                            const otherName = cmp.field;
                            if (!otherName) continue;
                            const op = (cmp.op || 'gte').toLowerCase();
                            const offset = cmp.offset || 0;
                            let left = v;
                            let right = this._getVal(otherName);
                            let compared = false;
                            if (this._isIntString(left) && this._isIntString(right)) {
                                left = parseInt(left, 10);
                                right = parseInt(right, 10) + (this._isIntString(offset) ? parseInt(offset, 10) : 0);
                                compared = true;
                            } else {
                                const lTs = this._parseDateToTs(left);
                                const rTs = this._parseDateToTs(right);
                                if (lTs !== null && rTs !== null) {
                                    const days = this._isIntString(offset) ? parseInt(offset, 10) : 0;
                                    left = lTs;
                                    right = rTs + days * 86400;
                                    compared = true;
                                }
                            }
                            if (compared) {
                                let ok = true;
                                switch (op) {
                                    case 'gt':
                                    case '>':
                                        ok = (left > right);
                                        break;
                                    case 'gte':
                                    case '>=':
                                        ok = (left >= right);
                                        break;
                                    case 'lt':
                                    case '<':
                                        ok = (left < right);
                                        break;
                                    case 'lte':
                                    case '<=':
                                        ok = (left <= right);
                                        break;
                                    case 'eq':
                                    case '==':
                                        ok = (left == right);
                                        break;
                                    case 'ne':
                                    case '!=':
                                        ok = (left != right);
                                        break;
                                }
                                if (!ok) {
                                    errs.push(cmp.message || ('Value must be ' + op + ' ' + otherName + (this._isIntString(offset) ? (' + ' + offset) : '') + '.'));
                                }
                            }
                        }
                    }
                    this.clientErrors[name] = errs;
                    return errs.length === 0;
                },
                validateAll() {
                    let ok = true;
                    for (const name in this.schema) {
                        if (!this.validateField(name)) ok = false;
                    }
                    return ok;
                }
            };
        };
    </script>
    <script>
        // Sidebar collapse state using a data attribute consumed by Tailwind data-variants
        (function () {
            try {
                const saved = localStorage.getItem('sidebar-collapsed');
                if (saved === 'true') {
                    document.documentElement.setAttribute('data-collapsed', 'true');
                }
            } catch (e) { /* no-op */
            }
        })();
    </script>
</head>
<body class="h-full">
<div id="app-main" x-data="{ active: '<?php echo $tab; ?>' }" @set-active.window="active = $event.detail">
    <?php
    // Autoload already required above, and $tab resolved
    // $tab is already set earlier; keep for clarity
    $tab = $tab ?? 'dashboard';

    // Navigation menu groups from Data Provider
    $menuGroups = \Components\Data\DataRegistry::navigation()->groups();

    // Determine active item within grouped structure (optional)
    $activeItem = null;
    foreach ($menuGroups as $grp) {
        foreach ($grp['items'] ?? [] as $it) {
            if ($it['key'] === $tab) {
                $activeItem = $it;
                break 2;
            }
        }
    }


    ?>


    <!-- Static sidebar for desktop (collapsible) -->

    <div id="app-sidebar"
         data-active="<?php echo \Components\Base::h($tab); ?>"
         class="fixed inset-y-0 z-[70] flex w-<?= BEEZUI_NAV_WIDTH ?>  group/sidebar group-data-[collapsed=true]/collapse:w-20 flex-col transition-all duration-300 ease-in-out">
        <div id="sidebar-pad"
             class="relative flex grow flex-col gap-y-5 overflow-y-auto overflow-x-hidden border-r border-divider/50 bg-muted group-data-[collapsed=true]/collapse:bg-canvas group-data-[collapsed=true]/collapse:border-0 px-6 transition-all duration-300 ease-in-out dark:before:pointer-events-none dark:before:absolute dark:before:inset-0 dark:before:bg-overlay/10">

<!--
            <div>
                <span class="inline-flex items-center gap-1.5 rounded-md border border-emerald-600/60 text-emerald-700 px-2 py-0.5 text-xs font-semibold">
                <span class="relative flex items-center justify-center">
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
                     stroke="currentColor" class="size-4">
                <path stroke-linecap="round" stroke-linejoin="round"
                      d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>
                </span>
                Production
                </span>

                <span class="inline-flex items-center gap-1.5 rounded-md border border-orange-500/60 text-orange-600 px-2 py-0.5 text-xs font-semibold">
                <span class="relative flex items-center justify-center">
                <span class="absolute inset-0 rounded-full border border-orange-500/30 border-dotted animate-pulse"></span>
                <span class="absolute inset-[3px] rounded-full border border-orange-500/50 animate-pulse"></span>
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                         stroke="currentColor"
                         stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4  animate-pulse"><path
                                d="M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"/><path
                                d="M6.453 15h11.094"/><path d="M8.5 2h7"/></svg>
                </span>
                Simulation
                </span>
            </div>
-->

            <div id="sidebar-header" class="relative flex h24  items-center text-sm tracking-tight  pt-6">


                <!-- Placeholder for logo or actions -->
                <div class="group-data-[collapsed=true]/collapse:hidden">
                    <span> MailBeez V5</span>
                    <span class="ml-2 ring ring-on-muted/70 rounded-lg px-2 text-xs text-on-muted ">beta 4</span>
                </div>
                <div class="group-data-[collapsed=true]/collapse:visible invisible translate-x-2 block">
                    <div class="ring ring-on-muted/70 rounded-lg px-2 text-xs text-on-muted w-full">b1</div>
                </div>


                <!--                  <img src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=indigo&shade=600" alt="Your Company" class="h-8 w-auto dark:hidden" />-->
                <!--                  <img src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company" class="h-8 w-auto not-dark:hidden" />-->
            </div>

            <div class="hidden bg-canvas rounded ring ring-divider px-3 py-2 text-xs text-secondary/70 dark:bg-canvas dark:text-white overflow-hidden">
                Search
            </div>

            <nav class="relative flex flex-1 flex-col  group-data-[collapsed=true]/collapse:translate-x-2!">
                <ul role="list" class="flex flex-1 flex-col gap-y-7">
                    <li>
                        <ul id="menu-list" role="list" class="-mx-2 transition-all  space-y-1 relative">
                            <?php foreach ($menuGroups as $group): ?>
                                <?php if (empty($group['items'])) continue; ?>
                                <li class="mt-4 first:mt-0">
                                    <div class="px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-secondary/60 group-data-[collapsed=true]/collapse:opacity-0 group-data-[collapsed=true]/collapse:h-2">
                                        <?php echo \Components\Base::h($group['header']); ?>
                                    </div>
                                    <ul class="space-y-1 transition-all group-data-[collapsed=true]/collapse:bg-muted group-data-[collapsed=true]/collapse:rounded-xl group-data-[collapsed=true]/collapse:shadow-xs  group-data-[collapsed=true]/collapse:px-1.5 group-data-[collapsed=true]/collapse:py-1.5 group-data-[collapsed=true]/collapse:mx-0">
                                        <?php foreach ($group['items'] as $item): $active = ($tab === $item['key']); ?>
                                            <li class="relative"
                                                x-data="{ tooltipVisible: false, tooltipText: '<?php echo \Components\Base::h($item['label']); ?>', tooltipArrow: true, tooltipPosition: 'right', tooltipX: 0, tooltipY: 0 }">

                                                <!-- Tooltip (teleported to body to avoid any overflow clipping) -->
                                                <template x-teleport="body">
                                                    <div x-ref="tooltip"
                                                         x-show="tooltipVisible && document.documentElement.getAttribute('data-collapsed') === 'true'"
                                                         x-cloak
                                                         :style="'position: fixed; top:' + tooltipY + 'px; left:' + tooltipX + 'px'"
                                                         class="w-auto text-sm z-[1000] pointer-events-none transform -translate-y-1/2">
                                                        <div x-show="tooltipVisible" x-transition
                                                             class="relative px-2 py-1 text-white rounded-md shadow bg-brand/90">
                                                            <p x-text="tooltipText"
                                                               class="block flex-shrink-0 text-xs whitespace-nowrap"></p>
                                                            <div x-ref="tooltipArrow" x-show="tooltipArrow"
                                                                 :class="{ 'left-0 -translate-y-1/2 top-1/2 h-2.5 -mt-px -translate-x-full' : tooltipPosition == 'right', 'bottom-0 -translate-x-1/2 left-1/2 w-2.5 translate-y-full' : tooltipPosition == 'top', 'right-0 -translate-y-1/2 top-1/2 h-2.5 -mt-px translate-x-full' : tooltipPosition == 'left', 'top-0 -translate-x-1/2 left-1/2 w-2.5 -translate-y-full' : tooltipPosition == 'bottom' }"
                                                                 class="inline-flex overflow-hidden absolute justify-center items-center">
                                                                <div :class="{ 'origin-top-right -rotate-45' : tooltipPosition == 'right', 'origin-top-left -rotate-45' : tooltipPosition == 'top', 'origin-top-left rotate-45' : tooltipPosition == 'left', 'origin-bottom-left rotate-45' : tooltipPosition == 'bottom' }"
                                                                     class="w-1.5 h-1.5 shadow bg-brand/90 transform"></div>
                                                            </div>
                                                        </div>
                                                    </div>
                                                </template>

                                                <a id="desk-tab-<?php echo \Components\Base::h($item['key']); ?>"
                                                   @click.prevent="active = '<?php echo $item['key']; ?>'"
                                                   :class="{ ' text-secondary! font-medium': active === '<?php echo $item['key']; ?>' }"
                                                   class="group flex items-center align-middle gap-x-3 rounded-md p-2 text-sm/6 text-secondary/80 hover:bg-muted hover:text-brand"
                                                   @mouseenter="(() => { const isCol = document.documentElement.getAttribute('data-collapsed') === 'true'; if (!isCol) return; const r = $el.getBoundingClientRect(); tooltipX = r.right + 8; tooltipY = r.top + r.height/2; tooltipVisible = true; })()"
                                                   @mouseleave="tooltipVisible = false">

                                                    <div>
                                                        <div aria-hidden="true"
                                                             class="size-4.5 shrink-0 text-secondary/70 group-hover:text-brand group-data-[active=true]:text-secondary">
                                                            <?php echo $item['icon']; ?>
                                                        </div>
                                                    </div>
                                                    <span class="transition-all group-data-[collapsed=true]/collapse:max-w-0 overflow-hidden text-nowrap inline-block"><?php echo \Components\Base::h($item['label']); ?></span>
                                                </a>
                                            </li>
                                        <?php endforeach; ?>
                                    </ul>
                                </li>
                            <?php endforeach; ?>
                        </ul>
                    </li>
                </ul>
            </nav>
            <div>

                <!--            <div class=" inline-flex items-center gap-x-1.5 rounded-md px-2 py-1 text-sm font-medium   inset-ring-gray-200 dark:text-white dark:inset-ring-white/10">-->
                <!--  <svg viewBox="0 0 6 6" aria-hidden="true" class="size-2 fill-green-500 dark:fill-green-400">-->
                <!--    <circle r="3" cx="3" cy="3" />-->
                <!--  </svg>-->
                <!--  Production-->
                <!--</div>-->

<!--                --><?php //include 'pages/components/mode.php'; ?>

            </div>
            <!-- Frontend switcher -->
            <div id="frontend-switcher" class="pb-2 group-data-[collapsed=true]/collapse:px-1.5">
                <div class="inline-flex items-center rounded-md overflow-hidden ring-1 ring-divider shadow-xs bg-elevated text-secondary group-data-[collapsed=true]/collapse:hidden">
                    <?php
                    echo \Components\Button::render('MailBeez V4', [
                            'variant' => 'ghost',
                            'size' => 'sm',
                            'attrs' => [
                                    'hx-post' => \Components\Router::url('switch_to_legacy', ['partial' => 1]),
                                    'hx-target' => 'body',
                                    'hx-swap' => 'innerHTML',
                                    'title' => 'Disable BeezUI and return to the legacy MailBeez admin',
                            ],
                    ]);
                    ?>
                </div>
            </div>
            <div class="hidden">
                <?php
                // Plan/Subscription Information box (extracted component)
                include BEEZUI_ROOT . '/pages/components/plan_info.php';
                ?>
            </div>

            <!-- Density switcher -->
            <div id="density-switcher"
                 class="mt-2 px-2 pb-2 group-data-[collapsed=true]/collapse:px-1.5  group-data-[collapsed=true]/collapse:hidden">
                <div class="text-[11px] font-semibold uppercase tracking-wide text-secondary/60 mb-1 group-data-[collapsed=true]/collapse:hidden">
                    Density
                </div>
                <div class="inline-flex items-center rounded-md overflow-hidden ring-1 ring-divider shadow-xs bg-elevated text-secondary">
                    <button type="button" data-density="normal"
                            class="px-2 py-1 text-xs leading-5 hover:bg-muted hover:text-brand data-[selected=true]:bg-muted data-[selected=true]:text-brand">
                        N
                    </button>
                    <div class="h-4 w-px bg-divider/70"></div>
                    <button type="button" data-density="compact"
                            class="px-2 py-1 text-xs leading-5 hover:bg-muted hover:text-brand data-[selected=true]:bg-muted data-[selected=true]:text-brand">
                        C
                    </button>
                    <div class="h-4 w-px bg-divider/70"></div>
                    <button type="button" data-density="very-compact"
                            class="px-2 py-1 text-xs leading-5 hover:bg-muted hover:text-brand data-[selected=true]:bg-muted data-[selected=true]:text-brand">
                        V
                    </button>
                </div>
            </div>
            <div id="sidebar-footer" class="relative flex h-10  group-data-[collapsed=true]/collapse:translate-x-4!">
                <button type="button" onclick="toggleCollapsed()"
                        class="flex items-center gap-2 rounded-md text-xs/6 text-secondary/70 hover:text-brand"
                >
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
                         stroke="currentColor" class="size-3 hidden group-data-[collapsed=true]/collapse:block">
                        <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5"/>
                    </svg>
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
                         stroke="currentColor" class="size-3 group-data-[collapsed=true]/collapse:hidden">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5"/>
                    </svg>
                    <span class="transition-all group-data-[collapsed=true]/collapse:hidden">Collapse</span>
                </button>
            </div>
        </div>
    </div>
    <!-- Global loading overlay for navigation/content loads -->
    <?php echo \Components\Base::loaderOverlay('app-loading', 'z-20 flex ml-' . BEEZUI_NAV_WIDTH . ' group-data-[collapsed=true]/collapse:ml-20'); ?>
    <?php foreach ($menuGroups as $group): ?>
        <?php foreach ($group['items'] ?? [] as $item):
            $key = $item['key'];
            $path = \Components\Router::path($key) ?: 'pages/' . $key . '.php';
            if (!is_file(BEEZUI_ROOT . '/' . $path)) continue;
            $isActive = ($key === $tab);
            $partialUrl = \Components\Router::url($key, ['partial' => 1]);
            ?>
            <div id="page-<?php echo $key; ?>"
                 x-show="active === '<?php echo $key; ?>'"
                 x-cloak
                 data-page="<?php echo $key; ?>"
                 class="" <?php if (!$isActive) { ?> hx-get="<?= $partialUrl; ?>" hx-trigger="intersect once" hx-swap="innerHTML"<?php } ?>>
                <?php if ($isActive) {
                    include BEEZUI_ROOT . '/' . $path;
                } ?>
            </div>

            <script>
                // Ensure sidebar collapse state is applied after HTMX swaps that render this layout

                document.addEventListener("htmx:load", () => {
                    try {
                        if (window.MBLoader) {
                            MBLoader.bindHtmxOverlay('app-container-<?php echo $key; ?>', 'app-loading', 350);
                            MBLoader.bindHtmxOverlay('page-<?php echo $key; ?>', 'app-loading', 350);
                        }
                    } catch (e) { /* no-op */
                    }
                });

            </script>

        <?php endforeach; ?>
    <?php endforeach; ?>


</div>

<script>

    // Density switcher bindings
    (function () {
        function applyDensity(mode) {
            try {
                var html = document.documentElement;
                html.classList.remove('density-compact', 'density-very-compact');
                if (mode === 'compact') html.classList.add('density-compact');
                else if (mode === 'very-compact') html.classList.add('density-very-compact');
                localStorage.setItem('ui-density', mode);
                var buttons = document.querySelectorAll('#density-switcher [data-density]');
                buttons.forEach(function (btn) {
                    var sel = btn.getAttribute('data-density');
                    btn.setAttribute('data-selected', (sel === mode) ? 'true' : 'false');
                });
            } catch (e) {
            }
        }

        window.applyDensity = applyDensity;
        document.addEventListener('DOMContentLoaded', function () {
            try {
                var saved = localStorage.getItem('ui-density') || 'normal';
                // set selected state based on saved
                var buttons = document.querySelectorAll('#density-switcher [data-density]');
                buttons.forEach(function (btn) {
                    var sel = btn.getAttribute('data-density');
                    btn.setAttribute('data-selected', (sel === saved) ? 'true' : 'false');
                });
                var container = document.getElementById('density-switcher');
                if (container) {
                    container.addEventListener('click', function (ev) {
                        var t = ev.target.closest('[data-density]');
                        if (!t) return;
                        ev.preventDefault();
                        applyDensity(t.getAttribute('data-density'));
                    });
                }
            } catch (e) {
            }
        });
    })();

    // Re-initialize after HTMX swaps
    // document.body.addEventListener('htmx:afterSwap', function (e) {
    //     try {
    //         var root = (e && e.detail && e.detail.target) ? e.detail.target : document.body;
    //         if (window.Alpine && typeof window.Alpine.initTree === 'function') {
    //             window.Alpine.initTree(root);
    //         }
    //     } catch (e3) {
    //     }
    // });

    function toggleCollapsed() {
        try {
            const html = document.documentElement;
            const isCollapsed = html.getAttribute('data-collapsed') === 'true';
            if (isCollapsed) {
                html.removeAttribute('data-collapsed');
                localStorage.setItem('sidebar-collapsed', 'false');
            } else {
                html.setAttribute('data-collapsed', 'true');
                localStorage.setItem('sidebar-collapsed', 'true');
            }
        } catch (e) { /* no-op */
        }
    }


    // Inform parent window when our (iframe) URL changes without reload (HTMX pushState/back/forward)
    (function () {
        function notifyParent() {
            try {
                if (window.parent && window.parent !== window) {
                    const params = new URLSearchParams(window.location.search || '');
                    const TAB_PARAM = <?php echo json_encode($tabParam); ?>;
                    const route = (params.get(TAB_PARAM) || 'dashboard').toLowerCase();
                    window.parent.postMessage({
                        type: 'iframe-location-update',
                        route: route,
                        search: window.location.search || ''
                    }, '*');
                }
            } catch (e) { /* no-op */
            }
        }

        // HTMX pushes into history when hx-push-url is used
        document.body.addEventListener('htmx:pushedIntoHistory', notifyParent);
        // Also capture browser navigation inside the iframe
        window.addEventListener('popstate', notifyParent);
    })();

    // Unified active menu setter used both by clicks and when parsing URL state
    const submenuMap = <?php
            $__map = [];
            foreach ($menuGroups as $grp) {
                foreach ($grp['items'] ?? [] as $it) {
                    $__map[$it['key']] = !empty($it['submenu']) ? $it['submenu'] : null;
                }
            }
            echo json_encode($__map);
            ?>;

    function setActiveMenu(tab, submenuUrl) {
        try {
            if (!tab) return;
            // Toggle data-active on the menu items themselves
            const links = document.querySelectorAll('a[id^="desk-tab-"]');
            let activeLink = null;
            links.forEach((link) => {
                const key = link.id.replace('desk-tab-', '');
                if (key === String(tab).toLowerCase()) {
                    activeLink = link;
                    link.setAttribute('data-active', 'true');
                } else {
                    link.removeAttribute('data-active');
                }
            });

        } catch (e) { /* no-op */
        }
    }

    // Dynamically set the active menu item based on the current URL's ?<tab>= parameter
    function setActiveMenuFromURL() {
        try {
            const params = new URLSearchParams(window.location.search || '');
            const TAB_PARAM = <?php echo json_encode($tabParam); ?>;
            const tab = (params.get(TAB_PARAM) || '').toLowerCase();
            if (!tab) return;
            // Tell Alpine to switch the visible page
            window.dispatchEvent(new CustomEvent('set-active', {detail: tab}));
            const submenuUrl = submenuMap[tab] || null;
            setActiveMenu(tab, submenuUrl);
        } catch (e) { /* no-op */
        }
    }

    // Push/replace the URL for a given tab key, then notify existing listeners
    function updateUrlForActive(tabKey, replace) {
        try {
            if (!tabKey) return;
            const TAB_PARAM = <?php echo json_encode($tabParam); ?>;
            const PAGE_PARAM = <?php echo json_encode($pageParam); ?>;
            const url = new URL(window.location.href);
            // Update params
            url.searchParams.set(TAB_PARAM, String(tabKey).toLowerCase());
            url.searchParams.delete('partial');
            if (PAGE_PARAM && PAGE_PARAM !== TAB_PARAM) url.searchParams.delete(PAGE_PARAM);
            const href = url.pathname + url.search + url.hash;
            const currentParams = new URLSearchParams(window.location.search || '');
            const currentTab = (currentParams.get(TAB_PARAM) || '').toLowerCase();
            if (replace || currentTab === String(tabKey).toLowerCase()) {
                history.replaceState({}, '', href);
            } else {
                history.pushState({}, '', href);
            }
            // Notify existing listeners (iframe parent + menu sync)
            document.body.dispatchEvent(new CustomEvent('htmx:pushedIntoHistory', {detail: {path: href}}));
        } catch (e) { /* no-op */
        }
    }

    // Keep active state in sync for HTMX-driven navigation and browser back/forward
    document.body.addEventListener('htmx:pushedIntoHistory', setActiveMenuFromURL);
    document.body.addEventListener('htmx:afterOnLoad', setActiveMenuFromURL);
    window.addEventListener('popstate', setActiveMenuFromURL);

    // Sidebar navigation → push URL (Alpine toggles DOM instantly)
    document.addEventListener('DOMContentLoaded', function () {
        try {
            var menu = document.getElementById('menu-list');
            if (menu) {
                menu.addEventListener('click', function (e) {
                    var a = e.target && e.target.closest ? e.target.closest('a[id^="desk-tab-"]') : null;
                    if (!a) return;
                    var key = a.id.replace('desk-tab-', '');
                    updateUrlForActive(key, false);
                });
            }
            // Ensure URL reflects the initially active tab on first load (no duplicate history entry)
            try {
                var params = new URLSearchParams(window.location.search || '');
                var TAB_PARAM = <?php echo json_encode($tabParam); ?>;
                var initial = <?php echo json_encode($tab); ?>;
                var current = (params.get(TAB_PARAM) || '').toLowerCase();
                if (String(initial).toLowerCase() !== current) {
                    updateUrlForActive(initial, true);
                }
            } catch (e2) { /* no-op */
            }
        } catch (e1) { /* no-op */
        }

        // htmx.logAll();
    });
    document.addEventListener("htmx:load", () => {
        // Bind global HTMX loader for navigation/content loads targeting #app-container and #app-main
        try {
            if (window.MBLoader) {
                MBLoader.bindHtmxOverlay('app-main', 'app-loading', 350);
            }
        } catch (e) { /* no-op */
        }
    });

    document.addEventListener('htmx:beforeSwap', () => {
        window._scrollY = window.scrollY;

        try {
            if (window.parent && window.parent !== window) {
                window.parent._iframeScrollY = window.parent.scrollY;
            }
        } catch (e) {}
    });

    document.addEventListener('htmx:afterSwap', () => {
        requestAnimationFrame(() => {
            // Restore scroll inside iframe
            if (typeof window._scrollY === 'number') {
                window.scrollTo(0, window._scrollY);
            }

            // Restore scroll in parent document
            try {
                if (window.parent && window.parent !== window) {
                    if (typeof window.parent._iframeScrollY === 'number') {
                        window.parent.scrollTo(0, window.parent._iframeScrollY);
                    }
                }
            } catch (e) {}
        });
    });

    // Listen for cross-frame requests coming from legacy iframes (modal/drawer)
    // Supported messages:
    //  - { type: 'mb:trigger', event: 'evt:name', detail?: {...} }
    //  - { type: 'mb:close', id?: 'element-id' }  → close a modal/drawer in the parent window
    window.addEventListener('message', function (event) {
        try {
            var data = event && event.data ? event.data : null;
            if (!data || !data.type) return;

            if (data.type === 'mb:trigger') {
                var ev = data.event || '';
                if (!ev) return;
                var detail = data.detail || {};
                try {
                    if (window.htmx && window.htmx.trigger) {
                        window.htmx.trigger(document.body, ev, detail);
                    } else if (document && document.body) {
                        document.body.dispatchEvent(new CustomEvent(ev, { detail: detail }));
                    }
                } catch (e3) { /* no-op */ }
                return;
            }

            if (data.type === 'mb:close') {
                try {
                    var id = data.id || null;
                    if (id) {
                        var el = document.getElementById(String(id));
                        if (el && typeof el.close === 'function') { el.close(); return; }
                    }
                    // Try common ids if none provided or element not found
                    var candidates = ['config-modal', 'config2-modal', 'ai-modal', 'email-preview', 'config-drawer'];
                    for (var i = 0; i < candidates.length; i++) {
                        var m = document.getElementById(candidates[i]);
                        if (m && typeof m.close === 'function') { m.close(); break; }
                    }
                } catch (e4) { /* no-op */ }
                return;
            }
        } catch (e) { /* no-op */ }
    });

</script>


<?= \Components\Drawer::render(['style' => 'floating']); ?>
<?= \Components\Modal::render(); ?>
<?= \Components\Modal::render(['id' => 'config2-modal']); ?>
<?= \Components\Modal::render(['id' => 'ai-modal', 'style' => 'ai']); ?>
<?= \Components\Modal::render(['id' => 'email-preview', 'style' => 'email_preview']); ?>
</body>
</html>
