<?php

declare(strict_types=1);

require_once dirname(__DIR__, 2) . '/system/bootstrap.php';
require_once __DIR__ . '/content/partials/forms-summary-widget.php';

$currentUser = myronRequireAuthenticatedUser();

$readModel = myronDashboardReadModel();
$snapshot = myronLicenseRepository()->currentSnapshot();
$csrfToken = myronCsrfToken();
$currentUserId = (string) $currentUser['id'];

$tabs = [];
if (myronUserCanAccessAdministration($currentUser)) {
    $tabs['administration'] = [
        'label' => 'Administration',
        'summary' => $readModel->administrationSummary(),
        'tips' => myronDashboardTipsFeedService()->tipsForContext('administration', $snapshot->plan),
    ];
}
if (myronUserCanAccessContent($currentUser)) {
    $tabs['content'] = [
        'label' => 'Content',
        'summary' => $readModel->contentSummary(),
        'tips' => myronDashboardTipsFeedService()->tipsForContext('content', $snapshot->plan),
    ];
}
if (myronUserCanAccessDesign($currentUser)) {
    $tabs['design'] = [
        'label' => 'Design',
        'summary' => $readModel->designSummary(),
        'tips' => myronDashboardTipsFeedService()->tipsForContext('design', $snapshot->plan),
    ];
}
$tabs['personal'] = [
    'label' => 'Personal',
    'summary' => [],
    'tips' => [],
];
$requestedTab = trim((string) ($_GET['tab'] ?? $_GET['dashboard_tab'] ?? ''));
$activeTab = isset($tabs[$requestedTab]) ? $requestedTab : (string) array_key_first($tabs);

$notes = myronDashboardNotesRepository()->listForUser($currentUserId);
$links = myronDashboardLinksRepository()->listForUser($currentUserId);
$inboxMessages = myronDashboardMessagesRepository()->listInbox($currentUserId);
$outboxMessages = myronDashboardMessagesRepository()->listOutbox($currentUserId);
$users = array_values(array_filter(
    myronAuthRepository()->listUsers(),
    static fn (array $user): bool => (string) ($user['id'] ?? '') !== $currentUserId && !empty($user['is_active'])
));
$replyToUserId = trim((string) ($_GET['to'] ?? ''));
$replyToUser = null;
foreach ($users as $user) {
    if ((string) ($user['id'] ?? '') === $replyToUserId) {
        $replyToUser = $user;
        break;
    }
}

/**
 * @param array<string, mixed> $card
 */
function myronDashboardRenderStatCard(array $card): void
{
    $title = (string) ($card['title'] ?? '');
    $value = (string) ($card['value'] ?? '');
    $text = (string) ($card['text'] ?? '');
    $href = trim((string) ($card['href'] ?? ''));
    $meta = is_array($card['meta'] ?? null) ? $card['meta'] : [];
    ?>
    <article class="sg-card mc-dashboard-stat">
      <div class="sg-card__header">
        <h2 class="sg-card__title"><?= myronEscape($title) ?></h2>
      </div>
      <div>
        <span class="mc-dashboard-stat__value"><?= myronEscape($value) ?></span>
        <?php if ($text !== ''): ?><p class="sg-card__text"><?= myronEscape($text) ?></p><?php endif; ?>
      </div>
      <?php if ($meta !== []): ?>
      <div class="mc-dashboard-stat__meta">
        <?php foreach ($meta as $item): ?>
        <span class="sg-pill<?= !empty($item['active']) ? ' sg-pill--active' : '' ?>"><?= myronEscape((string) ($item['label'] ?? '')) ?></span>
        <?php endforeach; ?>
      </div>
      <?php endif; ?>
      <?php if ($href !== ''): ?>
      <div class="sg-card__actions">
        <a class="sg-button sg-button--secondary" href="<?= myronEscape($href) ?>">Open</a>
      </div>
      <?php endif; ?>
    </article>
    <?php
}

/**
 * @param list<array<string, mixed>> $tips
 */
function myronDashboardRenderAiPanel(string $context, string $plan, array $tips): void
{
    $advanced = in_array(MyronEntitlementSnapshot::normalizePlan($plan), ['pro', 'agency'], true);
    $hasSecurityTip = count(array_filter($tips, static fn (array $tip): bool => !empty($tip['isSecurity']))) > 0;
    $className = 'sg-card mc-dashboard-ai-panel' . ($hasSecurityTip ? ' mc-dashboard-ai-panel--security' : '');
    ?>
    <article class="<?= myronEscape($className) ?>" data-mc-dashboard-ai-panel data-dashboard-context="<?= myronEscape($context) ?>" data-dashboard-plan="<?= myronEscape($plan) ?>">
      <div class="sg-card__header">
        <h2 class="sg-card__title">AI Panel</h2>
        <span class="sg-pill<?= $advanced ? ' sg-pill--active' : '' ?>"><?= myronEscape(ucfirst($plan)) ?></span>
      </div>
      <p class="sg-card__text"><?= $advanced
          ? 'AI-ready context for this workspace. Tips appear here now; embedded assistance can attach to this panel later.'
          : 'MCP guidance tips for this workspace. Upgrade-path AI behavior can attach here without changing the dashboard layout.' ?></p>
      <ul class="mc-dashboard-tips">
        <?php foreach ($tips as $tip): ?>
        <li class="mc-dashboard-tip">
          <h3 class="mc-dashboard-tip__title">
            <?php if (trim((string) ($tip['url'] ?? '')) !== ''): ?>
            <a href="<?= myronEscape((string) $tip['url']) ?>" rel="noopener"><?= myronEscape((string) ($tip['title'] ?? 'Dashboard tip')) ?></a>
            <?php else: ?>
            <?= myronEscape((string) ($tip['title'] ?? 'Dashboard tip')) ?>
            <?php endif; ?>
          </h3>
          <p class="mc-dashboard-tip__summary"><?= myronEscape((string) ($tip['summary'] ?? '')) ?></p>
          <?php if (!empty($tip['isSecurity'])): ?><span class="sg-pill">Security advisory</span><?php endif; ?>
        </li>
        <?php endforeach; ?>
      </ul>
    </article>
    <?php
}

function myronDashboardTruncate(string $value, int $length = 80): string
{
    $normalized = trim(preg_replace('/\s+/', ' ', $value) ?? $value);
    if (strlen($normalized) <= $length) {
        return $normalized;
    }

    return rtrim(substr($normalized, 0, max(0, $length - 1))) . '...';
}

/**
 * @param list<array<string, mixed>> $sections
 * @return list<array{title:string,url:string,type:string,search:string}>
 */
function myronDashboardAdminLinkOptions(array $sections): array
{
    $options = [];
    $seen = [];

    $addOption = static function (string $title, string $url, string $type, array $searchParts = []) use (&$options, &$seen): void {
        $title = trim($title);
        $url = trim($url);
        $type = trim($type);
        if ($title === '' || $url === '' || $url === '#' || isset($seen[$url])) {
            return;
        }

        $seen[$url] = true;
        $options[] = [
            'title' => $title,
            'url' => $url,
            'type' => in_array($type, ['admin', 'content', 'design'], true) ? $type : 'admin',
            'search' => trim(implode(' ', array_filter(array_merge([$title, $type], $searchParts)))),
        ];
    };

    foreach ($sections as $section) {
        $sectionKey = (string) ($section['key'] ?? '');
        $type = match ($sectionKey) {
            'content' => 'content',
            'design' => 'design',
            default => 'admin',
        };
        $sectionLabel = (string) ($section['label'] ?? '');
        $addOption($sectionLabel, (string) ($section['defaultHref'] ?? ''), $type, [$sectionKey]);

        $branches = is_array($section['branches'] ?? null) ? $section['branches'] : [];
        foreach ($branches as $branch) {
            if (!is_array($branch)) {
                continue;
            }

            foreach (is_array($branch['items'] ?? null) ? $branch['items'] : [] as $item) {
                if (!is_array($item) || !empty($item['disabled'])) {
                    continue;
                }

                $addOption(
                    (string) ($item['label'] ?? ''),
                    (string) ($item['href'] ?? ''),
                    $type,
                    [(string) ($branch['title'] ?? ''), (string) ($item['key'] ?? '')]
                );
            }
        }
    }

    return $options;
}

/**
 * @return list<array{title:string,url:string,type:string,search:string}>
 */
function myronDashboardLinkOptions(array $currentUser): array
{
    $options = myronDashboardAdminLinkOptions(myronAdminShellSections($currentUser));
    foreach (myronContentRepository()->listPublishedPages() as $page) {
        $title = trim((string) ($page['title'] ?? ''));
        $url = trim((string) ($page['url'] ?? ''));
        if ($title === '' || $url === '') {
            continue;
        }

        $options[] = [
            'title' => $title,
            'url' => $url,
            'type' => 'site',
            'search' => trim($title . ' site ' . (string) ($page['path'] ?? '')),
        ];
    }

    return $options;
}

/**
 * @param list<array<string, mixed>> $users
 */
function myronDashboardRenderUserCombobox(array $users, ?array $selectedUser = null): void
{
    $selectedId = is_array($selectedUser) ? (string) ($selectedUser['id'] ?? '') : '';
    $selectedLabel = is_array($selectedUser) ? (string) ($selectedUser['display_name'] ?? '') : '';
    ?>
    <div class="myron-combobox" data-myron-combobox>
      <div class="myron-combobox__control">
        <input class="myron-combobox__input" type="text" name="to_display_name" value="<?= myronEscape($selectedLabel) ?>" placeholder="Choose a user" aria-autocomplete="list" aria-expanded="false" data-myron-combobox-input>
        <input type="hidden" name="to_user_id" value="<?= myronEscape($selectedId) ?>" data-myron-combobox-value>
        <button class="myron-combobox__trigger" type="button" aria-label="Toggle users" aria-expanded="false" data-myron-combobox-trigger>
          <img class="mc-icon" src="<?= myronEscape(myronBuildAssetUrl('icons/bootstrap/person.svg')) ?>" alt="" aria-hidden="true">
        </button>
      </div>
      <div class="myron-combobox__panel" role="listbox" hidden data-myron-combobox-panel>
        <?php foreach ($users as $user): ?>
        <?php $label = (string) ($user['display_name'] ?? $user['email'] ?? 'User'); ?>
        <button class="myron-combobox__option" type="button" role="option" data-myron-combobox-option data-search-text="<?= myronEscape($label . ' ' . (string) ($user['email'] ?? '')) ?>" data-combobox-label="<?= myronEscape($label) ?>" data-combobox-value="<?= myronEscape((string) ($user['id'] ?? '')) ?>">
          <?= myronEscape($label) ?>
        </button>
        <?php endforeach; ?>
        <div class="myron-combobox__empty" hidden data-myron-combobox-empty>No matching users.</div>
      </div>
    </div>
    <?php
}

/**
 * @param list<array{title:string,url:string,type:string,search:string}> $options
 */
function myronDashboardRenderLinkCombobox(array $options): void
{
    ?>
    <div class="myron-combobox" data-myron-combobox>
      <div class="myron-combobox__control">
        <input class="myron-combobox__input" type="text" name="title" placeholder="Search routes and pages" aria-autocomplete="list" aria-expanded="false" data-myron-combobox-input>
        <input type="hidden" name="url" value="" data-myron-combobox-value>
        <button class="myron-combobox__trigger" type="button" aria-label="Toggle links" aria-expanded="false" data-myron-combobox-trigger>
          <img class="mc-icon" src="<?= myronEscape(myronBuildAssetUrl('icons/bootstrap/link.svg')) ?>" alt="" aria-hidden="true">
        </button>
      </div>
      <div class="myron-combobox__panel" role="listbox" hidden data-myron-combobox-panel>
        <?php foreach ($options as $option): ?>
        <button class="myron-combobox__option" type="button" role="option" data-myron-combobox-option data-search-text="<?= myronEscape($option['search']) ?>" data-combobox-label="<?= myronEscape($option['title']) ?>" data-combobox-value="<?= myronEscape($option['type'] . "\t" . $option['url']) ?>">
          <span><?= myronEscape($option['title']) ?></span>
          <span class="sg-badge"><?= myronEscape($option['type']) ?></span>
        </button>
        <?php endforeach; ?>
        <div class="myron-combobox__empty" hidden data-myron-combobox-empty>No matching links.</div>
      </div>
    </div>
    <?php
}

myronRenderAdminShellStart($currentUser, [
    'title' => 'Dashboard',
    'titleContext' => 'Dashboard',
    'activeItem' => 'dashboard',
]);
?>
<div class="mc-workspace__header">
  <span class="mc-workspace__eyebrow">Dashboard</span>
  <div class="mc-workspace__title-row">
    <h1 class="mc-workspace__title">Dashboard</h1>
  </div>
  <p class="mc-workspace__subtitle">Current site state across administration, content, and design workspaces.</p>
</div>

<div class="mc-page-canvas mc-page-canvas--site">
  <section class="sg-section mc-dashboard" data-mc-dashboard-tabs>
    <div class="mc-dashboard__tabs" role="tablist" aria-label="Dashboard contexts">
      <?php foreach ($tabs as $key => $tab): ?>
      <?php $isActive = $key === $activeTab; ?>
      <a
        class="sg-pill<?= $isActive ? ' sg-pill--active' : '' ?>"
        id="dashboard-tab-<?= myronEscape($key) ?>"
        href="<?= myronEscape(myronBuildAdminUrl('dashboard', ['tab' => $key]) . '#dashboard-panel-' . $key) ?>"
        role="tab"
        aria-selected="<?= $isActive ? 'true' : 'false' ?>"
        aria-controls="dashboard-panel-<?= myronEscape($key) ?>"
        tabindex="<?= $isActive ? '0' : '-1' ?>"
        data-mc-dashboard-tab="<?= myronEscape($key) ?>"
        data-mc-dashboard-legacy-url="<?= myronEscape('dashboard_tab=' . $key . '#dashboard-panel-' . $key) ?>"
      ><?= myronEscape((string) $tab['label']) ?></a>
      <?php endforeach; ?>
    </div>

    <?php foreach ($tabs as $key => $tab): ?>
    <?php
      $isActive = $key === $activeTab;
      $summary = is_array($tab['summary'] ?? null) ? $tab['summary'] : [];
    ?>
    <div
      class="mc-dashboard__tab-panel"
      id="dashboard-panel-<?= myronEscape($key) ?>"
      role="tabpanel"
      aria-labelledby="dashboard-tab-<?= myronEscape($key) ?>"
      aria-hidden="<?= $isActive ? 'false' : 'true' ?>"
      data-mc-dashboard-panel="<?= myronEscape($key) ?>"
      <?= $isActive ? '' : 'hidden' ?>
    >
      <div class="mc-dashboard__grid<?= $key === 'administration' ? ' mc-dashboard__grid--administration' : '' ?>">
        <?php if ($key === 'administration'): ?>
          <?php
            $license = is_array($summary['license'] ?? null) ? $summary['license'] : [];
            $team = is_array($summary['team'] ?? null) ? $summary['team'] : [];
            $ai = is_array($summary['aiActivity'] ?? null) ? $summary['aiActivity'] : [];
            $system = is_array($summary['system'] ?? null) ? $summary['system'] : [];
            myronDashboardRenderStatCard([
                'title' => 'License & Plan',
                'value' => ucfirst((string) ($license['plan'] ?? 'core')),
                'text' => 'Status: ' . (string) ($license['status'] ?? 'missing'),
                'href' => (string) ($license['href'] ?? ''),
                'meta' => [['label' => (string) ($license['environment'] ?? 'production'), 'active' => true]],
            ]);
            myronDashboardRenderStatCard([
                'title' => 'System',
                'value' => (string) ($system['siteTitle'] ?? 'MyronCMS'),
                'text' => 'Settings, mail, and AI readiness',
                'href' => (string) ($system['settingsHref'] ?? ''),
                'meta' => [
                    ['label' => !empty($system['mailConfigured']) ? 'Mail ready' : 'Mail not configured', 'active' => !empty($system['mailConfigured'])],
                    ['label' => !empty($system['aiConfigured']) ? 'AI ready' : 'AI not configured', 'active' => !empty($system['aiConfigured'])],
                ],
            ]);
            myronDashboardRenderStatCard([
                'title' => 'Team',
                'value' => (string) ($team['total'] ?? 0),
                'text' => 'Active operator accounts',
                'href' => (string) ($team['href'] ?? ''),
                'meta' => [
                    ['label' => (string) ($team['administrators'] ?? 0) . ' admin'],
                    ['label' => (string) ($team['content'] ?? 0) . ' content'],
                    ['label' => (string) ($team['design'] ?? 0) . ' design'],
                ],
            ]);
            if (myronUserCanAccessAdministration($currentUser)) {
                echo '<div class="sg-card mc-dashboard-forms-widget">';
                myronRenderFormsSummaryWidget();
                echo '</div>';
            }
            myronDashboardRenderStatCard([
                'title' => 'AI Activity',
                'value' => (string) ($ai['events24h'] ?? 0),
                'text' => 'Audit events in the last 24 hours',
                'href' => (string) ($ai['href'] ?? ''),
                'meta' => [['label' => (string) ($ai['connections'] ?? 0) . ' active connections']],
            ]);
            myronDashboardRenderAiPanel($key, $snapshot->plan, is_array($tab['tips'] ?? null) ? $tab['tips'] : []);
          ?>
        <?php elseif ($key === 'content'): ?>
          <?php
            $pages = is_array($summary['pages'] ?? null) ? $summary['pages'] : [];
            $assets = is_array($summary['assets'] ?? null) ? $summary['assets'] : [];
            $structure = is_array($summary['structure'] ?? null) ? $summary['structure'] : [];
            $recent = is_array($summary['recent'] ?? null) ? $summary['recent'] : [];
            myronDashboardRenderStatCard([
                'title' => 'Pages',
                'value' => (string) ($pages['total'] ?? 0),
                'text' => 'Published and draft pages',
                'href' => (string) ($pages['href'] ?? ''),
                'meta' => [
                    ['label' => (string) ($pages['published'] ?? 0) . ' published', 'active' => true],
                    ['label' => (string) ($pages['draft'] ?? 0) . ' draft'],
                ],
            ]);
            myronDashboardRenderStatCard([
                'title' => 'Assets',
                'value' => (string) array_sum(array_intersect_key($assets, array_flip(['image', 'video', 'audio', 'document']))),
                'text' => 'Files by media class',
                'href' => (string) ($assets['href'] ?? ''),
                'meta' => [
                    ['label' => (string) ($assets['image'] ?? 0) . ' image'],
                    ['label' => (string) ($assets['video'] ?? 0) . ' video'],
                    ['label' => (string) ($assets['document'] ?? 0) . ' docs'],
                ],
            ]);
            myronDashboardRenderStatCard([
                'title' => 'Categories & Menus',
                'value' => (string) ($structure['categories'] ?? 0),
                'text' => (string) ($structure['menus'] ?? 0) . ' menus configured',
                'href' => (string) ($structure['categoriesHref'] ?? ''),
            ]);
          ?>
          <article class="sg-card">
            <div class="sg-card__header"><h2 class="sg-card__title">Recent Activity</h2></div>
            <ul class="mc-dashboard-list">
              <?php foreach (is_array($recent['pages'] ?? null) ? $recent['pages'] : [] as $page): ?>
              <li class="mc-dashboard-list__item">
                <span class="mc-dashboard-list__label"><?= myronEscape((string) ($page['title'] ?? 'Untitled')) ?></span>
                <span class="mc-dashboard-list__value"><?= myronEscape((string) ($page['publication_state'] ?? 'draft')) ?></span>
              </li>
              <?php endforeach; ?>
            </ul>
            <div class="sg-card__actions"><a class="sg-button sg-button--secondary" href="<?= myronEscape((string) ($recent['href'] ?? myronBuildAdminUrl('content.pages'))) ?>">Open</a></div>
          </article>
        <?php elseif ($key === 'design'): ?>
          <?php
            $inventory = is_array($summary['inventory'] ?? null) ? $summary['inventory'] : [];
            $tokens = is_array($summary['tokens'] ?? null) ? $summary['tokens'] : [];
            $coverage = is_array($summary['coverage'] ?? null) ? $summary['coverage'] : [];
            myronDashboardRenderStatCard([
                'title' => 'Design Inventory',
                'value' => (string) ($inventory['components'] ?? 0),
                'text' => 'Governed components',
                'href' => (string) ($inventory['href'] ?? ''),
                'meta' => [
                    ['label' => (string) ($inventory['sections'] ?? 0) . ' sections'],
                    ['label' => (string) ($inventory['templates'] ?? 0) . ' templates'],
                ],
            ]);
            myronDashboardRenderStatCard([
                'title' => 'Token Customizations',
                'value' => (string) ($tokens['customized'] ?? 0),
                'text' => 'Active token override entries',
                'href' => (string) ($tokens['href'] ?? ''),
            ]);
          ?>
          <article class="sg-card">
            <div class="sg-card__header"><h2 class="sg-card__title">Template Coverage</h2></div>
            <ul class="mc-dashboard-list">
              <?php foreach (is_array($coverage['topTemplates'] ?? null) ? $coverage['topTemplates'] : [] as $template): ?>
              <li class="mc-dashboard-list__item">
                <span class="mc-dashboard-list__label"><?= myronEscape((string) ($template['name'] ?? $template['sourceTemplateId'] ?? 'Template')) ?></span>
                <span class="mc-dashboard-list__value"><?= myronEscape((string) ($template['pageCount'] ?? 0)) ?> pages</span>
              </li>
              <?php endforeach; ?>
            </ul>
            <div class="sg-card__actions"><a class="sg-button sg-button--secondary" href="<?= myronEscape((string) ($coverage['href'] ?? myronBuildAdminUrl('content.templates'))) ?>">Open</a></div>
          </article>
        <?php elseif ($key === 'personal'): ?>
          <div class="mc-dashboard-personal__columns">
            <section class="mc-dashboard-personal__col" aria-label="Personal notes">
              <div class="mc-dashboard-personal__col-header">
                <h2 class="mc-dashboard-personal__title">Notes</h2>
              </div>
              <form class="sg-form-grid mc-dashboard-personal__form" method="post" action="<?= myronEscape(myronBuildAdminUrl('dashboard.notesSave')) ?>">
                <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
                <label class="sg-field">
                  <span class="sg-field__label">Title</span>
                  <input class="sg-field__control" type="text" name="title" required>
                </label>
                <label class="sg-field">
                  <span class="sg-field__label">Note</span>
                  <textarea class="sg-field__control" name="content" rows="4"></textarea>
                </label>
                <div class="sg-card__actions">
                  <button class="sg-button sg-button--primary" type="submit">Save</button>
                </div>
              </form>
              <ul class="mc-dashboard-personal-list">
                <?php foreach ($notes as $note): ?>
                <?php $noteId = (string) ($note['id'] ?? ''); ?>
                <li class="mc-dashboard-personal-list__item">
                  <span class="mc-dashboard-personal-list__label"><?= myronEscape(myronDashboardTruncate((string) ($note['title'] ?? 'Untitled'), 56)) ?></span>
                  <button class="mc-dashboard-personal-list__caret" type="button" aria-label="Open note" data-mc-sidesheet-open="dashboard-note-<?= myronEscape($noteId) ?>">
                    <img class="mc-icon" src="<?= myronEscape(myronBuildAssetUrl('icons/bootstrap/chevron-right.svg')) ?>" alt="" aria-hidden="true">
                  </button>
                </li>
                <?php endforeach; ?>
                <?php if ($notes === []): ?>
                <li class="mc-dashboard-personal-list__empty">No notes yet.</li>
                <?php endif; ?>
              </ul>
            </section>

            <section class="mc-dashboard-personal__col" aria-label="Personal messages">
              <div class="mc-dashboard-personal__col-header">
                <h2 class="mc-dashboard-personal__title">Messages</h2>
              </div>
              <form class="sg-form-grid mc-dashboard-personal__form" method="post" action="<?= myronEscape(myronBuildAdminUrl('dashboard.messagesSend')) ?>">
                <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
                <label class="sg-field">
                  <span class="sg-field__label">To</span>
                  <?php myronDashboardRenderUserCombobox($users, $replyToUser); ?>
                </label>
                <label class="sg-field">
                  <span class="sg-field__label">Message</span>
                  <textarea class="sg-field__control" name="body" rows="4" required></textarea>
                </label>
                <div class="sg-card__actions">
                  <button class="sg-button sg-button--primary" type="submit">Send</button>
                </div>
              </form>
              <div class="mc-dashboard-personal__section">
                <h3 class="mc-dashboard-personal__subtitle">Inbox</h3>
                <ul class="mc-dashboard-personal-list">
                  <?php foreach ($inboxMessages as $message): ?>
                  <?php
                    $messageId = (string) ($message['id'] ?? '');
                    $isUnread = ($message['read_at'] ?? null) === null || (string) ($message['read_at'] ?? '') === '';
                  ?>
                  <li class="mc-dashboard-personal-list__item">
                    <span class="mc-dashboard-personal-list__stack">
                      <span class="mc-dashboard-personal-list__label">
                        <?php if ($isUnread): ?><span class="mc-dashboard-personal-list__dot" aria-label="Unread"></span><?php endif; ?>
                        <?= myronEscape((string) ($message['from_display_name'] ?? 'User')) ?>
                      </span>
                      <span class="mc-dashboard-personal-list__meta"><?= myronEscape(myronDashboardTruncate((string) ($message['body'] ?? ''), 72)) ?> · <?= myronEscape((string) ($message['created_at'] ?? '')) ?></span>
                    </span>
                    <button
                      class="mc-dashboard-personal-list__caret"
                      type="button"
                      aria-label="Open message"
                      data-mc-sidesheet-open="dashboard-message-<?= myronEscape($messageId) ?>"
                      data-mc-message-read-url="<?= myronEscape(myronBuildAdminUrl('dashboard.messagesRead')) ?>"
                      data-mc-message-id="<?= myronEscape($messageId) ?>"
                      data-mc-message-csrf="<?= myronEscape($csrfToken) ?>"
                    >
                      <img class="mc-icon" src="<?= myronEscape(myronBuildAssetUrl('icons/bootstrap/chevron-right.svg')) ?>" alt="" aria-hidden="true">
                    </button>
                  </li>
                  <?php endforeach; ?>
                  <?php if ($inboxMessages === []): ?>
                  <li class="mc-dashboard-personal-list__empty">Inbox is empty.</li>
                  <?php endif; ?>
                </ul>
              </div>
              <div class="mc-dashboard-personal__divider"></div>
              <div class="mc-dashboard-personal__section">
                <h3 class="mc-dashboard-personal__subtitle">Outbox</h3>
                <ul class="mc-dashboard-personal-list">
                  <?php foreach ($outboxMessages as $message): ?>
                  <li class="mc-dashboard-personal-list__item">
                    <details class="mc-dashboard-personal-list__details">
                      <summary>
                        <span><?= myronEscape((string) ($message['to_display_name'] ?? 'User')) ?></span>
                        <span><?= myronEscape(myronDashboardTruncate((string) ($message['body'] ?? ''), 64)) ?></span>
                      </summary>
                      <p><?= nl2br(myronEscape((string) ($message['body'] ?? ''))) ?></p>
                      <span class="mc-dashboard-personal-list__meta"><?= myronEscape((string) ($message['created_at'] ?? '')) ?></span>
                    </details>
                  </li>
                  <?php endforeach; ?>
                  <?php if ($outboxMessages === []): ?>
                  <li class="mc-dashboard-personal-list__empty">Outbox is empty.</li>
                  <?php endif; ?>
                </ul>
              </div>
            </section>

            <section class="mc-dashboard-personal__col" aria-label="Personal links">
              <div class="mc-dashboard-personal__col-header">
                <h2 class="mc-dashboard-personal__title">Links</h2>
              </div>
              <form class="sg-form-grid mc-dashboard-personal__form" method="post" action="<?= myronEscape(myronBuildAdminUrl('dashboard.linksSave')) ?>">
                <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
                <input type="hidden" name="link_type" value="">
                <label class="sg-field">
                  <span class="sg-field__label">Link</span>
                  <?php myronDashboardRenderLinkCombobox(myronDashboardLinkOptions($currentUser)); ?>
                </label>
                <div class="sg-card__actions">
                  <button class="sg-button sg-button--primary" type="submit">Save</button>
                </div>
              </form>
              <div class="mc-page-grid mc-page-grid--dashboard-links" role="table" aria-label="Personal links" data-mc-sortable-grid>
                <div class="mc-page-grid__row mc-page-grid__row--head" role="row">
                  <span data-mc-sort-key="title" data-mc-sort-type="text"><button class="mc-page-grid__sort" type="button">Title</button></span>
                  <span data-mc-sort-key="type" data-mc-sort-type="text"><button class="mc-page-grid__sort" type="button">Type</button></span>
                  <span class="mc-page-grid__header-actions">Delete</span>
                </div>
                <?php foreach ($links as $link): ?>
                <div class="mc-page-grid__row" role="row" data-mc-filter-row data-sort-title="<?= myronEscape((string) ($link['title'] ?? '')) ?>" data-sort-type="<?= myronEscape((string) ($link['link_type'] ?? '')) ?>">
                  <span class="mc-page-grid__cell"><a class="mc-page-grid__link" href="<?= myronEscape((string) ($link['url'] ?? '#')) ?>"><?= myronEscape((string) ($link['title'] ?? 'Link')) ?></a></span>
                  <span class="mc-page-grid__cell"><span class="sg-badge"><?= myronEscape((string) ($link['link_type'] ?? 'site')) ?></span></span>
                  <span class="mc-page-grid__cell mc-page-grid__cell--actions">
                    <form class="mc-page-grid__action-form" method="post" action="<?= myronEscape(myronBuildAdminUrl('dashboard.linksDelete')) ?>">
                      <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
                      <input type="hidden" name="link_id" value="<?= myronEscape((string) ($link['id'] ?? '')) ?>">
                      <button class="sg-button sg-button--secondary" type="submit">Delete</button>
                    </form>
                  </span>
                </div>
                <?php endforeach; ?>
                <?php if ($links === []): ?>
                <div class="mc-page-grid__row" role="row" data-mc-filter-row data-sort-title="" data-sort-type="">
                  <span class="mc-page-grid__cell">No saved links.</span>
                  <span class="mc-page-grid__cell"></span>
                  <span class="mc-page-grid__cell"></span>
                </div>
                <?php endif; ?>
              </div>
            </section>
          </div>
        <?php endif; ?>
      </div>
      <?php if (!in_array($key, ['administration', 'personal'], true)) { myronDashboardRenderAiPanel($key, $snapshot->plan, is_array($tab['tips'] ?? null) ? $tab['tips'] : []); } ?>
    </div>
    <?php endforeach; ?>
  </section>
</div>
<?php foreach ($notes as $note): ?>
<?php
  $noteId = (string) ($note['id'] ?? '');
  ob_start();
?>
  <form class="sg-form-grid" method="post" action="<?= myronEscape(myronBuildAdminUrl('dashboard.notesSave')) ?>">
    <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
    <input type="hidden" name="note_id" value="<?= myronEscape($noteId) ?>">
    <label class="sg-field">
      <span class="sg-field__label">Title</span>
      <input class="sg-field__control" type="text" name="title" value="<?= myronEscape((string) ($note['title'] ?? '')) ?>" required>
    </label>
    <label class="sg-field">
      <span class="sg-field__label">Note</span>
      <textarea class="sg-field__control" name="content" rows="10"><?= myronEscape((string) ($note['content'] ?? '')) ?></textarea>
    </label>
    <div class="sg-card__actions">
      <button class="sg-button sg-button--primary" type="submit">Save</button>
    </div>
  </form>
  <form class="sg-form-grid mc-side-sheet__danger" method="post" action="<?= myronEscape(myronBuildAdminUrl('dashboard.notesDelete')) ?>">
    <input type="hidden" name="csrf_token" value="<?= myronEscape($csrfToken) ?>">
    <input type="hidden" name="note_id" value="<?= myronEscape($noteId) ?>">
    <button class="sg-button sg-button--secondary" type="submit">Delete</button>
  </form>
<?php
  myronRenderAdminSidesheet('dashboard-note-' . $noteId, (string) ($note['title'] ?? 'Note'), (string) ob_get_clean(), ['size' => 'sm']);
?>
<?php endforeach; ?>
<?php foreach ($inboxMessages as $message): ?>
<?php
  $messageId = (string) ($message['id'] ?? '');
  ob_start();
?>
  <dl class="mc-dashboard-message-detail">
    <div><dt>From</dt><dd><?= myronEscape((string) ($message['from_display_name'] ?? 'User')) ?></dd></div>
    <div><dt>Date</dt><dd><?= myronEscape((string) ($message['created_at'] ?? '')) ?></dd></div>
  </dl>
  <p class="mc-dashboard-message-detail__body"><?= nl2br(myronEscape((string) ($message['body'] ?? ''))) ?></p>
  <div class="sg-card__actions">
    <a class="sg-button sg-button--primary" href="<?= myronEscape(myronBuildAdminUrl('dashboard', ['tab' => 'personal', 'to' => (string) ($message['from_user_id'] ?? '')])) ?>">Reply</a>
  </div>
<?php
  myronRenderAdminSidesheet('dashboard-message-' . $messageId, 'Message', (string) ob_get_clean(), ['size' => 'sm']);
?>
<?php endforeach; ?>
<?php myronRenderAdminShellEnd(); ?>
