<?php
declare(strict_types=1);

if (!isset($title)) $title = t('site');
$u = $me ?? current_user();

$uri = current_uri();

/* =========================
   helpers (safe)
========================= */
if (!function_exists('lang_label')) {
  function lang_label(string $l): string {
    return match ($l) {
      'uk' => 'UA',
      'en' => 'EN',
      'ru' => 'RU',
      default => strtoupper($l),
    };
  }
}

if (!function_exists('nav_groups_label')) {
  function nav_groups_label(): string {
    $lbl = '';
    if (function_exists('t')) $lbl = (string)t('groups');

    if ($lbl === '' || $lbl === 'groups') {
      $l = function_exists('lang') ? (string)lang() : 'uk';
      $lbl = match ($l) {
        'en' => 'Groups',
        'ru' => 'Группы',
        default => 'Групи',
      };
    }
    return $lbl;
  }
}

if (!function_exists('nav_board_label')) {
  function nav_board_label(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'Classifieds',
      'ru' => 'Доска объявлений',
      default => 'Дошка оголошень',
    };
  }
}

if (!function_exists('nav_users_label')) {
  function nav_users_label(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'Users',
      'ru' => 'Пользователи',
      default => 'Користувачі',
    };
  }
}

/* ===== notifications labels ===== */
if (!function_exists('nav_notifications_label')) {
  function nav_notifications_label(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'Notifications',
      'ru' => 'Уведомления',
      default => 'Повідомлення',
    };
  }
}

if (!function_exists('nav_notifications_empty')) {
  function nav_notifications_empty(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'No notifications yet.',
      'ru' => 'Пока нет уведомлений.',
      default => 'Поки що немає повідомлень.',
    };
  }
}

if (!function_exists('nav_notifications_all')) {
  function nav_notifications_all(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'All notifications',
      'ru' => 'Все уведомления',
      default => 'Усі повідомлення',
    };
  }
}

if (!function_exists('nav_notifications_new')) {
  function nav_notifications_new(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'new',
      'ru' => 'новое',
      default => 'нове',
    };
  }
}

/* ===== search labels (3 languages) ===== */
if (!function_exists('nav_search_placeholder')) {
  function nav_search_placeholder(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'Search: people, music, videos, groups',
      'ru' => 'Поиск: люди, музыка, видео, группы',
      default => 'Пошук: люди, музика, відео, групи',
    };
  }
}
if (!function_exists('nav_search_btn_label')) {
  function nav_search_btn_label(): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'Search',
      'ru' => 'Найти',
      default => 'Пошук',
    };
  }
}

/**
 * Чистить URL від сміттєвих/технічних/трекінг параметрів для canonical/to/back.
 */
if (!function_exists('hdr_strip_noise_params')) {
  function hdr_strip_noise_params(string $url): string {
    $url = trim($url);
    if ($url === '') return $url;

    $p = parse_url($url);
    if (!is_array($p)) return $url;

    $scheme = $p['scheme'] ?? '';
    $host   = $p['host'] ?? '';
    $port   = isset($p['port']) ? (':' . $p['port']) : '';
    $path   = $p['path'] ?? '';
    $query  = $p['query'] ?? '';
    $frag   = isset($p['fragment']) && $p['fragment'] !== '' ? ('#' . $p['fragment']) : '';

    $qs = [];
    if ($query !== '') parse_str($query, $qs);

    if (!empty($qs)) {
      $removeExact = [
        'lang','to','debug_flash','clear_flash','show_ok',
        'pjax','ajax','_t','ts','nonce','token',
        '_nrd','_nid',
        'gclid','fbclid','yclid','ymclid','gbraid','wbraid',
        '_ga','_gid','_gac','_gl','mc_cid','mc_eid',
        'ref','refid','source','src','spm','from','igshid'
      ];

      foreach (array_keys($qs) as $k) {
        $lk = strtolower((string)$k);

        if (str_starts_with($lk, 'utm_')) {
          unset($qs[$k]);
          continue;
        }
        if (in_array($lk, $removeExact, true)) {
          unset($qs[$k]);
          continue;
        }
      }

      if (!empty($qs)) ksort($qs);
    }

    $newQuery = (!empty($qs)) ? http_build_query($qs) : '';

    $base = '';
    if ($scheme !== '' && $host !== '') {
      $base = $scheme . '://' . $host . $port . $path;
    } else {
      $base = ($path !== '') ? $path : $url;
    }

    return $base . ($newQuery !== '' ? ('?' . $newQuery) : '') . $frag;
  }
}

if (!function_exists('hdr_safe_local_url')) {
  function hdr_safe_local_url(string $raw, string $fallback = '/'): string {
    $raw = rawurldecode(trim($raw));
    if ($raw === '') return $fallback;

    if (preg_match('~^https?://~i', $raw)) {
      $p = parse_url($raw);
      $path = (string)($p['path'] ?? '/');
      $q = isset($p['query']) && (string)$p['query'] !== '' ? ('?' . (string)$p['query']) : '';
      $f = isset($p['fragment']) && (string)$p['fragment'] !== '' ? ('#' . (string)$p['fragment']) : '';
      $raw = $path . $q . $f;
    }

    if (function_exists('safe_local_path')) {
      try {
        return (string)safe_local_path($raw, $fallback);
      } catch (Throwable $e) {
        return $fallback;
      }
    }

    if ($raw === '' || $raw[0] !== '/' || str_starts_with($raw, '//')) return $fallback;
    return $raw;
  }
}

/* =========================
   notifications helpers
========================= */
if (!function_exists('hdr_db_has_table')) {
  function hdr_db_has_table(PDO $pdo, string $table): bool {
    if (function_exists('db_has_table')) {
      try {
        return (bool)db_has_table($pdo, $table);
      } catch (Throwable $e) {}
    }

    try {
      $st = $pdo->prepare("
        SELECT 1
        FROM information_schema.tables
        WHERE table_schema = DATABASE()
          AND table_name = ?
        LIMIT 1
      ");
      $st->execute([$table]);
      return (bool)$st->fetchColumn();
    } catch (Throwable $e) {
      return false;
    }
  }
}

if (!function_exists('hdr_db_has_column')) {
  function hdr_db_has_column(PDO $pdo, string $table, string $column): bool {
    if (function_exists('db_has_column')) {
      try {
        return (bool)db_has_column($pdo, $table, $column);
      } catch (Throwable $e) {}
    }

    try {
      $st = $pdo->prepare("
        SELECT 1
        FROM information_schema.columns
        WHERE table_schema = DATABASE()
          AND table_name = ?
          AND column_name = ?
        LIMIT 1
      ");
      $st->execute([$table, $column]);
      return (bool)$st->fetchColumn();
    } catch (Throwable $e) {
      return false;
    }
  }
}

if (!function_exists('hdr_notification_actor_label')) {
  function hdr_notification_actor_label(array $n): string {
    $full = trim((string)($n['actor_full_name'] ?? ''));
    if ($full !== '') return $full;

    $fn = trim((string)($n['actor_first_name'] ?? ''));
    $ln = trim((string)($n['actor_last_name'] ?? ''));
    $nm = trim($fn . ' ' . $ln);
    if ($nm !== '') return $nm;

    $un = trim((string)($n['actor_username'] ?? ''));
    if ($un !== '') return '@' . $un;

    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => 'Someone',
      'ru' => 'Кто-то',
      default => 'Хтось',
    };
  }
}

if (!function_exists('hdr_notification_time_ago')) {
  function hdr_notification_time_ago(?string $dt): string {
    $dt = trim((string)$dt);
    if ($dt === '') return '';

    try {
      $ts = strtotime($dt);
      if ($ts <= 0) return $dt;

      $diff = time() - $ts;
      if ($diff < 0) $diff = 0;

      $l = function_exists('lang') ? (string)lang() : 'uk';

      if ($diff < 60) {
        return match ($l) {
          'en' => 'just now',
          'ru' => 'только что',
          default => 'щойно',
        };
      }

      $mins = (int)floor($diff / 60);
      if ($mins < 60) {
        return match ($l) {
          'en' => $mins . ' min ago',
          'ru' => $mins . ' мин назад',
          default => $mins . ' хв тому',
        };
      }

      $hrs = (int)floor($diff / 3600);
      if ($hrs < 24) {
        return match ($l) {
          'en' => $hrs . ' h ago',
          'ru' => $hrs . ' ч назад',
          default => $hrs . ' год тому',
        };
      }

      $days = (int)floor($diff / 86400);
      if ($days < 7) {
        return match ($l) {
          'en' => $days . ' d ago',
          'ru' => $days . ' дн назад',
          default => $days . ' дн тому',
        };
      }

      return date('d.m.Y H:i', $ts);
    } catch (Throwable $e) {
      return $dt;
    }
  }
}

if (!function_exists('hdr_notification_default_text')) {
  function hdr_notification_default_text(array $n): string {
    $type = trim((string)($n['type'] ?? ''));
    $actor = hdr_notification_actor_label($n);
    $l = function_exists('lang') ? (string)lang() : 'uk';

    return match ($type) {
      'post_like' => match ($l) {
        'en' => $actor . ' liked your post',
        'ru' => $actor . ' поставил(а) лайк вашему посту',
        default => $actor . ' поставив(ла) лайк вашому посту',
      },
      'post_dislike' => match ($l) {
        'en' => $actor . ' disliked your post',
        'ru' => $actor . ' поставил(а) дизлайк вашему посту',
        default => $actor . ' поставив(ла) дизлайк вашому посту',
      },
      'comment_like' => match ($l) {
        'en' => $actor . ' liked your comment',
        'ru' => $actor . ' поставил(а) лайк вашему комментарию',
        default => $actor . ' поставив(ла) лайк вашому коментарю',
      },
      'comment_dislike' => match ($l) {
        'en' => $actor . ' disliked your comment',
        'ru' => $actor . ' поставил(а) дизлайк вашему комментарию',
        default => $actor . ' поставив(ла) дизлайк вашому коментарю',
      },
      'friend_request' => match ($l) {
        'en' => $actor . ' sent you a friend request',
        'ru' => $actor . ' отправил(а) вам заявку в друзья',
        default => $actor . ' надіслав(ла) вам запит у друзі',
      },
      'group_invite' => match ($l) {
        'en' => $actor . ' invited you to a group',
        'ru' => $actor . ' пригласил(а) вас в группу',
        default => $actor . ' запросив(ла) вас до групи',
      },
      'group_join_request' => match ($l) {
        'en' => $actor . ' requested to join your group',
        'ru' => $actor . ' подал(а) заявку в вашу группу',
        default => $actor . ' подав(ла) заявку до вашої групи',
      },
      default => trim((string)($n['message'] ?? '')) !== ''
        ? trim((string)$n['message'])
        : match ($l) {
            'en' => 'New notification',
            'ru' => 'Новое уведомление',
            default => 'Нове повідомлення',
          },
    };
  }
}

if (!function_exists('hdr_notification_text')) {
  function hdr_notification_text(array $n): string {
    $msg = trim((string)($n['message'] ?? ''));
    $actor = hdr_notification_actor_label($n);

    if ($msg !== '') {
      $msgLower = mb_strtolower($msg, 'UTF-8');
      $actorLower = mb_strtolower(trim((string)$actor), 'UTF-8');

      if ($actorLower !== '' && str_starts_with($msgLower, $actorLower)) {
        return $msg;
      }
      return $actor . ' ' . $msg;
    }

    return hdr_notification_default_text($n);
  }
}

if (!function_exists('hdr_notification_group_url')) {
  function hdr_notification_group_url(array $n): string {
    $groupId = (int)($n['group_id'] ?? 0);
    $entityType = trim((string)($n['entity_type'] ?? ''));
    $entityId = (int)($n['entity_id'] ?? 0);

    if ($groupId <= 0 && $entityType === 'group' && $entityId > 0) {
      $groupId = $entityId;
    }

    $groupSlug = trim((string)($n['notif_group_slug'] ?? ''));

    if ($groupSlug !== '') {
      return '/functional/group/view.php?g=' . rawurlencode($groupSlug);
    }

    if ($groupId > 0) {
      return '/functional/group/view.php?id=' . $groupId;
    }

    return '/group.php';
  }
}

if (!function_exists('hdr_notification_group_members_url')) {
  function hdr_notification_group_members_url(array $n): string {
    $groupId = (int)($n['group_id'] ?? 0);
    $entityType = trim((string)($n['entity_type'] ?? ''));
    $entityId = (int)($n['entity_id'] ?? 0);

    if ($groupId <= 0 && $entityType === 'group' && $entityId > 0) {
      $groupId = $entityId;
    }

    if ($groupId > 0) {
      return '/functional/group/members.php?id=' . $groupId;
    }

    return hdr_notification_group_url($n);
  }
}

if (!function_exists('hdr_notification_target_url')) {
  function hdr_notification_target_url(array $n): string {
    $type = trim((string)($n['type'] ?? ''));
    $entityType = trim((string)($n['entity_type'] ?? ''));
    $entityId = (int)($n['entity_id'] ?? 0);
    $postId = (int)($n['post_id'] ?? 0);
    $groupId = (int)($n['group_id'] ?? 0);

    if ($type === 'friend_request') {
      return '/functional/friends/';
    }

    if ($type === 'group_invite') {
      return hdr_notification_group_url($n);
    }

    if ($type === 'group_join_request') {
      return hdr_notification_group_members_url($n);
    }

    if ($entityType === 'comment' && $entityId > 0) {
      if ($groupId > 0) {
        if ($postId > 0) {
          return hdr_notification_group_url($n) . '#post-' . $postId;
        }
        return hdr_notification_group_url($n);
      }
      return '/#comment-' . $entityId;
    }

    if ($postId > 0) {
      if ($groupId > 0) {
        return hdr_notification_group_url($n) . '#post-' . $postId;
      }
      return '/#post-' . $postId;
    }

    if ($entityType === 'post' && $entityId > 0) {
      if ($groupId > 0) {
        return hdr_notification_group_url($n) . '#post-' . $entityId;
      }
      return '/#post-' . $entityId;
    }

    if ($entityType === 'group' && $entityId > 0) {
      return hdr_notification_group_url($n);
    }

    return '/';
  }
}

if (!function_exists('hdr_notification_url')) {
  function hdr_notification_url(array $n): string {
    $target = hdr_notification_target_url($n);
    $nid = (int)($n['id'] ?? 0);
    if ($nid <= 0) return $target;

    $p = parse_url($target);
    $path = (string)($p['path'] ?? '/');
    $qs = [];
    if (!empty($p['query'])) parse_str((string)$p['query'], $qs);

    $qs['_nrd'] = '1';
    $qs['_nid'] = (string)$nid;
    $qs['to']   = $target;

    $query = http_build_query($qs);
    return $path . ($query !== '' ? ('?' . $query) : '');
  }
}

if (!function_exists('hdr_notification_avatar')) {
  function hdr_notification_avatar(array $n): string {
    $avatar = trim((string)($n['actor_avatar_path'] ?? ''));
    if ($avatar !== '') return $avatar;

    $label = hdr_notification_actor_label($n);
    $ch = function_exists('mb_substr')
      ? (string)mb_substr($label, 0, 1, 'UTF-8')
      : substr($label, 0, 1);

    $svg = '<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">'
         . '<rect width="48" height="48" rx="14" fill="#5b7aa6"/>'
         . '<text x="50%" y="56%" dominant-baseline="middle" text-anchor="middle" '
         . 'font-family="Arial,sans-serif" font-size="20" font-weight="700" fill="white">'
         . htmlspecialchars($ch !== '' ? $ch : '?', ENT_QUOTES, 'UTF-8')
         . '</text></svg>';

    return 'data:image/svg+xml;utf8,' . rawurlencode($svg);
  }
}

/* to= для set_lang.php: не тягнемо сміття */


$to = urlencode(hdr_strip_noise_params((string)$uri));

$flashDebug = (isset($_GET['debug_flash']) && (string)($_GET['debug_flash']) === '1');
$clearFlash = (isset($_GET['clear_flash']) && (string)($_GET['clear_flash']) === '1');

$flashShowOk =
    (isset($show_flash_ok) && $show_flash_ok === true) ||
    $flashDebug ||
    (isset($_GET['show_ok']) && (string)($_GET['show_ok']) === '1');

if (!function_exists('flash_pop')) {
  function flash_pop(string $key): ?string {
    $val = null;

    if (isset($_SESSION['_flash']) && is_array($_SESSION['_flash']) && array_key_exists($key, $_SESSION['_flash'])) {
      $val = $_SESSION['_flash'][$key];
      unset($_SESSION['_flash'][$key]);
    }

    if ($val === null && isset($_SESSION['flash']) && is_array($_SESSION['flash']) && array_key_exists($key, $_SESSION['flash'])) {
      $val = $_SESSION['flash'][$key];
      unset($_SESSION['flash'][$key]);
    }

    if ($val === null && function_exists('flash_get')) {
      try { $val = flash_get($key); } catch (Throwable $e) { $val = null; }
    }

    if ($val === null && isset($_SESSION) && array_key_exists($key, $_SESSION)) {
      $val = $_SESSION[$key];
      unset($_SESSION[$key]);
    }

    if (isset($_SESSION)) {
      if (isset($_SESSION['_flash']) && is_array($_SESSION['_flash'])) {
        unset($_SESSION['_flash'][$key]);
        if ($key === 'err') unset($_SESSION['_flash']['error']);
        if ($key === 'ok')  unset($_SESSION['_flash']['success']);
      }
      if (isset($_SESSION['flash']) && is_array($_SESSION['flash'])) {
        unset($_SESSION['flash'][$key]);
        if ($key === 'err') unset($_SESSION['flash']['error']);
        if ($key === 'ok')  unset($_SESSION['flash']['success']);
      }

      unset($_SESSION[$key], $_SESSION['flash_'.$key], $_SESSION['_flash_'.$key]);

      if ($key === 'err') {
        unset($_SESSION['err'], $_SESSION['error'], $_SESSION['flash_error'], $_SESSION['_flash_error']);
      }
      if ($key === 'ok') {
        unset($_SESSION['ok'], $_SESSION['success'], $_SESSION['flash_success'], $_SESSION['_flash_success']);
      }
    }

    if (!is_string($val)) return null;
    $val = trim($val);
    return $val === '' ? null : $val;
  }
}

if ($clearFlash && isset($_SESSION)) {
  if (isset($_SESSION['_flash']) && is_array($_SESSION['_flash'])) $_SESSION['_flash'] = [];
  if (isset($_SESSION['flash']) && is_array($_SESSION['flash'])) $_SESSION['flash'] = [];

  unset(
    $_SESSION['err'], $_SESSION['error'], $_SESSION['flash_error'], $_SESSION['_flash_error'],
    $_SESSION['ok'], $_SESSION['success'], $_SESSION['flash_success'], $_SESSION['_flash_success'],
    $_SESSION['flash_err'], $_SESSION['_flash_err'], $_SESSION['flash_ok'], $_SESSION['_flash_ok']
  );

  $path = (string)parse_url((string)($_SERVER['REQUEST_URI'] ?? '/'), PHP_URL_PATH);
  if ($path === '') $path = '/';
  header('Location: ' . $path . ($flashDebug ? '?debug_flash=1' : ''));
  exit;
}

$hdrSearchValue = trim((string)($_GET['q'] ?? ''));

/* =========================
   mark notification as read (before any output)
========================= */
if (
  $u
  && isset($pdo) && $pdo instanceof PDO
  && hdr_db_has_table($pdo, 'notifications')
  && ((string)($_GET['_nrd'] ?? '') === '1')
) {
  $nid = (int)($_GET['_nid'] ?? 0);

  $fallbackTarget = hdr_strip_noise_params((string)$uri);
  if ($fallbackTarget === '') $fallbackTarget = '/';

  $target = hdr_safe_local_url((string)($_GET['to'] ?? ''), $fallbackTarget);

  if ($nid > 0) {
    try {
      $st = $pdo->prepare("
        UPDATE notifications
        SET is_read = 1,
            read_at = COALESCE(read_at, NOW())
        WHERE id = ?
          AND user_id = ?
      ");
      $st->execute([$nid, (int)($u['id'] ?? 0)]);
    } catch (Throwable $e) {
      // не ламаємо перехід через notification
    }
  }

  if (!headers_sent()) {
    header('Location: ' . $target, true, 302);
    exit;
  }

  echo '<meta http-equiv="refresh" content="0;url=' . h($target) . '">';
  echo '<script>location.href=' . json_encode($target) . ';</script>';
  exit;
}

/* =========================
   SEO (централізовано)
========================= */
$seoFile = __DIR__ . '/seo.php';
if (is_file($seoFile)) {
  require_once $seoFile;
}

$path = (string)parse_url((string)($_SERVER['REQUEST_URI'] ?? '/'), PHP_URL_PATH);
if ($path === '') $path = '/';

$siteName = function_exists('t') ? (string)t('site') : 'VMEREGI';

if (!function_exists('hdr_default_desc')) {
  function hdr_default_desc(string $siteName): string {
    $l = function_exists('lang') ? (string)lang() : 'uk';
    return match ($l) {
      'en' => $siteName . ' — social network. Posts, groups, friends, music and messaging.',
      'ru' => $siteName . ' — социальная сеть. Посты, группы, друзья, музыка и общение.',
      default => $siteName . ' — соціальна мережа. Пости, групи, друзі, музика та спілкування.',
    };
  }
}

$defaultDesc = hdr_default_desc($siteName);
$meta_desc   = (isset($meta_desc) && is_string($meta_desc) && trim($meta_desc) !== '') ? (string)$meta_desc : $defaultDesc;
$og_image    = (isset($og_image) && is_string($og_image)) ? (string)$og_image : '';

$isPrivateArea =
  str_starts_with($path, '/admin') ||
  str_starts_with($path, '/messages') ||
  str_starts_with($path, '/profile/setting') ||
  str_starts_with($path, '/functional/search') ||
  str_starts_with($path, '/functional/files') ||
  str_starts_with($path, '/friends') ||
  str_starts_with($path, '/games') ||
  str_starts_with($path, '/functional/games') ||
  in_array($path, ['/login.php','/register.php','/logout.php','/set_lang.php'], true);

if (isset($seo_noindex) && $seo_noindex === true) $isPrivateArea = true;

if ($isPrivateArea && !headers_sent()) {
  header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet', true);
}

$canonicalRaw = '';
if (isset($canonical) && is_string($canonical) && trim($canonical) !== '') {
  $canonicalRaw = (string)$canonical;
} else {
  if (function_exists('abs_url') && function_exists('current_uri')) {
    $canonicalRaw = (string)abs_url((string)current_uri());
  } else {
    $canonicalRaw = '';
  }
}
$canonical = ($canonicalRaw !== '') ? hdr_strip_noise_params($canonicalRaw) : '';

if (function_exists('seo_set')) {
  seo_set([
    'site_name'   => $siteName,
    'title'       => (string)$title,
    'description' => (string)$meta_desc,
    'canonical'   => (string)$canonical,
    'image'       => (string)$og_image,
    'noindex'     => $isPrivateArea,
    'hreflang'    => false,
    'jsonld'      => !$isPrivateArea,
    'type'        => 'website',
  ]);
  if ($isPrivateArea && function_exists('seo_noindex')) {
    seo_noindex(true);
  }
}

if (!function_exists('csrf_field')) {
  function csrf_field(): string {
    if (session_status() !== PHP_SESSION_ACTIVE) @session_start();
    if (empty($_SESSION['csrf_token'])) {
      $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return '<input type="hidden" name="csrf" value="' . htmlspecialchars((string)$_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8') . '">';
  }
}

$hdrNotifications = [];
$hdrNotifUnread = 0;

if ($u && isset($pdo) && $pdo instanceof PDO && hdr_db_has_table($pdo, 'notifications')) {
  try {
    $notifHasActor = hdr_db_has_table($pdo, 'users');
    $notifHasGroups = hdr_db_has_table($pdo, 'groups');
    $notifGroupHasSlug = $notifHasGroups && hdr_db_has_column($pdo, 'groups', 'slug');
    $notifGroupHasName = $notifHasGroups && hdr_db_has_column($pdo, 'groups', 'name');

    $sql = "
      SELECT
        n.*
        " . ($notifHasActor ? ",
        au.username   AS actor_username,
        au.first_name AS actor_first_name,
        au.last_name  AS actor_last_name,
        au.full_name  AS actor_full_name,
        au.avatar_path AS actor_avatar_path
        " : ",
        NULL AS actor_username,
        NULL AS actor_first_name,
        NULL AS actor_last_name,
        NULL AS actor_full_name,
        NULL AS actor_avatar_path
        ") . "
        " . ($notifHasGroups
          ? ",
        " . ($notifGroupHasSlug ? "ng.slug" : "NULL") . " AS notif_group_slug,
        " . ($notifGroupHasName ? "ng.name" : "NULL") . " AS notif_group_name
        "
          : ",
        NULL AS notif_group_slug,
        NULL AS notif_group_name
        ") . "
      FROM notifications n
      " . ($notifHasActor ? "LEFT JOIN users au ON au.id = n.actor_user_id" : "") . "
      " . ($notifHasGroups ? "LEFT JOIN `groups` ng ON ng.id = n.group_id" : "") . "
      WHERE n.user_id = ?
      ORDER BY n.is_read ASC, n.created_at DESC, n.id DESC
      LIMIT 12
    ";
    $stN = $pdo->prepare($sql);
    $stN->execute([(int)$u['id']]);
    $hdrNotifications = $stN->fetchAll(PDO::FETCH_ASSOC) ?: [];
  } catch (Throwable $e) {
    $hdrNotifications = [];
  }

  try {
    $stU = $pdo->prepare("
      SELECT COUNT(*)
      FROM notifications
      WHERE user_id = ?
        AND is_read = 0
    ");
    $stU->execute([(int)$u['id']]);
    $hdrNotifUnread = (int)$stU->fetchColumn();
  } catch (Throwable $e) {
    $hdrNotifUnread = 0;
  }
}

$logoutBack = '/';

/* для сторінок, де не можна показувати відновлений scroll */
$hdrDisableScrollRestore = !empty($disable_scroll_restore);
?>
<!doctype html>
<html lang="<?= h(lang()) ?>">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <?php if ($hdrDisableScrollRestore): ?>
    <script>
      (function () {
        try {
          if ('scrollRestoration' in history) {
            history.scrollRestoration = 'manual';
          }
        } catch (e) {}
      })();
    </script>
  <?php endif; ?>

  <?php if (function_exists('seo_render_head')): ?>
    <?= seo_render_head() ?>
  <?php else: ?>
    <title><?= h((string)$title) ?></title>
    <?php if (!empty($meta_desc)): ?><meta name="description" content="<?= h((string)$meta_desc) ?>"><?php endif; ?>
    <?php if (!empty($canonical)): ?><link rel="canonical" href="<?= h((string)$canonical) ?>"><?php endif; ?>
    <meta name="robots" content="<?= $isPrivateArea ? 'noindex,nofollow,noarchive,nosnippet' : 'index,follow' ?>">
  <?php endif; ?>

  <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">

  <link href="/css/style.css?v=1" rel="stylesheet">
  <link href="/css/profile.css?v=101" rel="stylesheet">
  <link href="/css/audio_global_player.css?v=1" rel="stylesheet">

  <style>
    .hdr-notif-toggle::after{ display:none !important; }
    .hdr-notif-menu{
      width:min(420px, calc(100vw - 24px));
      padding:0;
      overflow:hidden;
      border-radius:16px;
      border:1px solid rgba(0,0,0,.08);
      box-shadow:0 18px 40px rgba(0,0,0,.16);
    }
    .hdr-notif-head{
      display:flex;
      align-items:center;
      justify-content:space-between;
      gap:12px;
      padding:12px 14px;
      border-bottom:1px solid rgba(0,0,0,.06);
      background:#fff;
      font-weight:700;
    }
    .hdr-notif-list{
      max-height:460px;
      overflow:auto;
      background:#fff;
    }
    .hdr-notif-item{
      display:flex;
      gap:10px;
      padding:12px 14px;
      text-decoration:none;
      color:inherit;
      border-bottom:1px solid rgba(0,0,0,.05);
      background:#fff;
    }
    .hdr-notif-item:hover{
      background:rgba(31,58,95,.05);
      color:inherit;
    }
    .hdr-notif-item.unread{
      background:rgba(25,135,84,.08);
    }
    .hdr-notif-ava{
      width:44px;
      height:44px;
      border-radius:14px;
      overflow:hidden;
      flex:0 0 auto;
      background:#e9ecef;
    }
    .hdr-notif-ava img{
      width:100%;
      height:100%;
      object-fit:cover;
      display:block;
    }
    .hdr-notif-body{
      min-width:0;
      flex:1 1 auto;
    }
    .hdr-notif-text{
      font-size:14px;
      line-height:1.25;
      color:#1f2937;
      word-wrap:break-word;
    }
    .hdr-notif-meta{
      margin-top:4px;
      display:flex;
      align-items:center;
      gap:8px;
      flex-wrap:wrap;
      font-size:12px;
      color:#6b7280;
    }
    .hdr-notif-empty{
      padding:18px 14px;
      color:#6b7280;
      background:#fff;
    }
    .hdr-notif-foot{
      padding:10px 14px;
      border-top:1px solid rgba(0,0,0,.06);
      background:#fff;
      text-align:center;
    }
    .hdr-notif-badge{
      position:absolute;
      top:-6px;
      right:-6px;
      min-width:20px;
      height:20px;
      border-radius:999px;
      padding:0 6px;
      display:flex;
      align-items:center;
      justify-content:center;
      font-size:11px;
      font-weight:700;
      line-height:1;
      background:#dc3545;
      color:#fff;
      border:2px solid #16304f;
    }
    .hdr-notif-new-dot{
      display:inline-block;
      width:8px;
      height:8px;
      border-radius:999px;
      background:#198754;
      flex:0 0 auto;
    }
    @media (max-width: 991.98px){
      .hdr-nav-actions{
        align-items:flex-start !important;
      }
    }
  </style>
</head>
<body class="bg-app">

<nav class="navbar navbar-expand-lg navbar-dark nav-app shadow-sm">
  <div class="container">
    <a class="navbar-brand fw-bold" href="/"><?= h(t('site')) ?></a>

    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navMain">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navMain">
      <ul class="navbar-nav me-auto">
        <li class="nav-item"><a class="nav-link" href="/"><?= h(t('feed')) ?></a></li>
        <li class="nav-item"><a class="nav-link" href="/users.php"><?= h(nav_users_label()) ?></a></li>
        <li class="nav-item"><a class="nav-link" href="/group.php"><?= h(nav_groups_label()) ?></a></li>
        <li class="nav-item"><a class="nav-link" href="/board.php"><?= h(nav_board_label()) ?></a></li>
      </ul>

      <form class="d-flex my-2 my-lg-0 me-lg-3 flex-grow-1 flex-lg-grow-0" action="/functional/search/" method="get" role="search">
        <div class="input-group input-group-sm">
          <input
            type="search"
            class="form-control"
            name="q"
            value="<?= h($hdrSearchValue) ?>"
            placeholder="<?= h(nav_search_placeholder()) ?>"
            aria-label="<?= h(nav_search_placeholder()) ?>"
            maxlength="120"
            autocomplete="off"
          >
          <button class="btn btn-light" type="submit"><?= h(nav_search_btn_label()) ?></button>
        </div>
      </form>

      <div class="d-flex align-items-center gap-2 hdr-nav-actions">
        <div class="dropdown">
          <button class="btn btn-sm btn-outline-light dropdown-toggle" data-bs-toggle="dropdown">
            <?= h(lang_label(lang())) ?>
          </button>
          <ul class="dropdown-menu dropdown-menu-end">
            <li><a class="dropdown-item" data-no-pjax="1" rel="nofollow" href="/set_lang.php?lang=uk&to=<?= $to ?>">UA</a></li>
            <li><a class="dropdown-item" data-no-pjax="1" rel="nofollow" href="/set_lang.php?lang=en&to=<?= $to ?>">EN</a></li>
            <li><a class="dropdown-item" data-no-pjax="1" rel="nofollow" href="/set_lang.php?lang=ru&to=<?= $to ?>">RU</a></li>
          </ul>
        </div>

        <?php if ($u): ?>
          <div class="dropdown">
            <button class="btn btn-sm btn-outline-light position-relative dropdown-toggle hdr-notif-toggle" data-bs-toggle="dropdown" aria-expanded="false">
              <span aria-hidden="true">🔔</span>
              <span class="ms-1"><?= h(nav_notifications_label()) ?></span>
              <?php if ($hdrNotifUnread > 0): ?>
                <span class="hdr-notif-badge"><?= (int)min($hdrNotifUnread, 99) ?></span>
              <?php endif; ?>
            </button>

            <div class="dropdown-menu dropdown-menu-end hdr-notif-menu">
              <div class="hdr-notif-head">
                <span><?= h(nav_notifications_label()) ?></span>
                <?php if ($hdrNotifUnread > 0): ?>
                  <span class="badge text-bg-danger"><?= (int)$hdrNotifUnread ?></span>
                <?php endif; ?>
              </div>

              <div class="hdr-notif-list">
                <?php if (!$hdrNotifications): ?>
                  <div class="hdr-notif-empty"><?= h(nav_notifications_empty()) ?></div>
                <?php else: ?>
                  <?php foreach ($hdrNotifications as $n): ?>
                    <?php
                      $nUrl = hdr_notification_url($n);
                      $nText = hdr_notification_text($n);
                      $nAvatar = hdr_notification_avatar($n);
                      $nUnread = (int)($n['is_read'] ?? 0) === 0;
                      $nTime = hdr_notification_time_ago((string)($n['created_at'] ?? ''));
                    ?>
                    <a class="hdr-notif-item <?= $nUnread ? 'unread' : '' ?>" href="<?= h($nUrl) ?>" data-no-pjax="1">
                      <div class="hdr-notif-ava">
                        <img src="<?= h($nAvatar) ?>" alt="">
                      </div>
                      <div class="hdr-notif-body">
                        <div class="hdr-notif-text"><?= h($nText) ?></div>
                        <div class="hdr-notif-meta">
                          <?php if ($nUnread): ?>
                            <span class="hdr-notif-new-dot"></span>
                            <span><?= h(nav_notifications_new()) ?></span>
                          <?php endif; ?>
                          <?php if ($nTime !== ''): ?>
                            <span><?= h($nTime) ?></span>
                          <?php endif; ?>
                        </div>
                      </div>
                    </a>
                  <?php endforeach; ?>
                <?php endif; ?>
              </div>

              <div class="hdr-notif-foot">
                <a class="text-decoration-none" href="/messages/"><?= h(nav_notifications_all()) ?></a>
              </div>
            </div>
          </div>

          <span class="text-white-50 small d-none d-md-inline">
            <?= h((string)$u['username']) ?>
          </span>

          <form method="post" action="/logout.php" class="m-0 p-0" data-no-pjax="1">
            <?= csrf_field() ?>
            <input type="hidden" name="back" value="<?= h($logoutBack) ?>">
            <button class="btn btn-sm btn-light" type="submit"><?= h(t('logout')) ?></button>
          </form>
        <?php else: ?>
          <a class="btn btn-sm btn-outline-light" data-no-pjax="1" href="/login.php"><?= h(t('login')) ?></a>
          <a class="btn btn-sm btn-light" data-no-pjax="1" href="/register.php"><?= h(t('register')) ?></a>
        <?php endif; ?>
      </div>
    </div>
  </div>
</nav>

<main class="container my-4" id="appMain">
<?php
$err = flash_pop('err');
$ok  = flash_pop('ok');
?>
<?php if ($err): ?>
  <div class="alert alert-danger" data-src="header"><?= h($err) ?></div>
<?php endif; ?>

<?php if ($ok && $flashShowOk): ?>
  <div class="alert alert-success" data-src="header"><?= h($ok) ?></div>
<?php endif; ?>

<?php
$accountRestrictionNotice = $GLOBALS['_ACCOUNT_RESTRICTION_NOTICE'] ?? null;
?>
<?php if (is_array($accountRestrictionNotice) && !empty($accountRestrictionNotice['has_any'])): ?>
  <div class="modal fade" id="accountRestrictionModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title"><?= h((string)($accountRestrictionNotice['title'] ?? '')) ?></h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <?php if (trim((string)($accountRestrictionNotice['text'] ?? '')) !== ''): ?>
            <div class="mb-2"><?= h((string)$accountRestrictionNotice['text']) ?></div>
          <?php endif; ?>

          <?php $arItems = $accountRestrictionNotice['items'] ?? []; ?>
          <?php if (is_array($arItems) && $arItems): ?>
            <ul class="mb-2 ps-3">
              <?php foreach ($arItems as $arItem): ?>
                <li><?= h((string)$arItem) ?></li>
              <?php endforeach; ?>
            </ul>
          <?php endif; ?>

          <?php if (trim((string)($accountRestrictionNotice['reason'] ?? '')) !== ''): ?>
            <div class="small text-muted"><strong><?= h(ar_t('Причина', 'Причина', 'Reason')) ?>:</strong> <?= h((string)$accountRestrictionNotice['reason']) ?></div>
          <?php endif; ?>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
        </div>
      </div>
    </div>
  </div>
  <script>
  document.addEventListener('DOMContentLoaded', function () {
    var el = document.getElementById('accountRestrictionModal');
    if (!el || typeof bootstrap === 'undefined' || !bootstrap.Modal) return;
    try {
      bootstrap.Modal.getOrCreateInstance(el).show();
    } catch (e) {}
  });
  </script>
<?php endif; ?>

<?php if ($flashDebug): ?>
  <div class="alert alert-warning" style="white-space:pre-wrap" data-src="header-debug">
DEBUG FLASH
- err (after pop): <?= h((string)($err ?? 'NULL')) ?>


- ok  (after pop): <?= h((string)($ok ?? 'NULL')) ?>


SESSION SNAPSHOT (keys):
<?= h(json_encode(array_keys($_SESSION ?? []), JSON_UNESCAPED_UNICODE)) ?>


SESSION['_flash']:
<?= h(json_encode($_SESSION['_flash'] ?? null, JSON_UNESCAPED_UNICODE)) ?>


SESSION['flash']:
<?= h(json_encode($_SESSION['flash'] ?? null, JSON_UNESCAPED_UNICODE)) ?>


<a class="btn btn-sm btn-outline-dark mt-2" href="?debug_flash=1&clear_flash=1">Очистити flash зараз</a>
  </div>
<?php endif; ?>