<?php
declare(strict_types=1);

/**
 * /profile/index.php
 * Профіль користувача:
 * - шапка (обкладинка без обрізання + квадратна аватарка справа)
 * - пости користувача з вкладеннями/опитуваннями/коментарями/реакціями
 * - аватар + ПІБ + @username
 * - редагування/видалення постів/коментарів (власник або admin)
 * - репости (якщо є posts.repost_post_id)
 * - ДРУЗІ / ПІДПИСКИ:
 *   - кнопки дружби/підписки у шапці профілю
 *   - якщо профіль закритий (якщо є колонка приватності) — бачать тільки друзі/власник/admin
 *   - взаємодія (лайк/дизлайк/комент/репост/голосування) — тільки друзі/власник/admin (для закритого)
 *
 * ОНОВЛЕНО (закриті профілі):
 * - якщо профіль закритий і гість відкриває його -> редірект на /login.php
 * - якщо профіль закритий і користувач авторизований (але не друг/власник/admin):
 *    показуємо мінімум (ПІБ, @нік, кнопка "Додати в друзі" + текст "Користувач закрив свій профіль")
 *    пости/вкладення/коментарі НЕ показуємо
 *
 * ✅ УНІФІКАЦІЯ UI:
 * - Emoji picker підключається з /includes/emoji_picker.php (єдиний для стрічки/груп/профілю/коментарів)
 * - Lightbox підключається з /includes/lightbox.php (єдиний)
 *
 * ✅ ОНОВЛЕНО:
 * - лайк/дизлайк для постів у профілі: іконка + видимий лічильник, без тексту "Лайк/Дизлайк"
 * - лайк/дизлайк для коментарів у профілі: такий самий стиль, як у стрічці/групах
 * - AJAX-оновлення реакцій без перезавантаження сторінки
 * - для fallback додано back=#post-ID / #comment-ID, щоб не кидало вгору
 * - посилання в постах/коментарях профілю тепер клікабельні
 * - для посилань у постах/коментарях профілю додано preview-картки, як у стрічці
 * - ПІБ та @username автора коментаря тепер клікабельні й ведуть на профіль
 *
 * ✅ ОНОВЛЕНО (реклама):
 * - підключено /functional/reclama/_lib.php
 * - для особистих постів у профілі повернуто кнопку "Рекламувати"
 * - кнопка показується за тією ж логікою, що і в стрічці
 * - для рекламованих постів показується бейдж "РЕКЛАМА" і кнопка переходу
 *
 * ✅ ОНОВЛЕНО (фотоальбоми):
 * - підключено /functional/albums/_lib.php
 * - вкладка "Фотоальбом" тепер жива:
 *   - створення альбому
 *   - список альбомів
 *   - приватність альбому
 *   - перехід у /functional/albums/view.php
 *   - видалення альбому
 */

require_once __DIR__ . '/../includes/start.php';

$reclamaLib = __DIR__ . '/../functional/reclama/_lib.php';
if (is_file($reclamaLib)) {
  require_once $reclamaLib;
}

$albumsLib = __DIR__ . '/../functional/albums/_lib.php';
$albumsLibOk = false;
if (is_file($albumsLib)) {
  require_once $albumsLib;
  $albumsLibOk = true;
}

/** @var PDO|null $pdo */
/** @var array|null $me */
$pdo = (isset($pdo) && $pdo instanceof PDO) ? $pdo : db();
$me  = $me ?? current_user();

$viewUsername = trim((string)($_GET['u'] ?? ''));
$viewUserId   = (int)($_GET['id'] ?? 0);

if (!$me && $viewUsername === '' && $viewUserId <= 0) {
  header('Location: /login.php');
  exit;
}

/* ===== Load profile user ONLY from DB (щоб аватар/ПІБ завжди були актуальні) ===== */
$profileUser = null;

if ($viewUsername !== '') {
  $st = $pdo->prepare("SELECT * FROM users WHERE username=? LIMIT 1");
  $st->execute([$viewUsername]);
  $profileUser = $st->fetch(PDO::FETCH_ASSOC) ?: null;
} elseif ($viewUserId > 0) {
  $st = $pdo->prepare("SELECT * FROM users WHERE id=? LIMIT 1");
  $st->execute([$viewUserId]);
  $profileUser = $st->fetch(PDO::FETCH_ASSOC) ?: null;
} else {
  $meIdTmp = (int)(is_array($me) ? ($me['id'] ?? 0) : 0);
  if ($meIdTmp > 0) {
    $st = $pdo->prepare("SELECT * FROM users WHERE id=? LIMIT 1");
    $st->execute([$meIdTmp]);
    $profileUser = $st->fetch(PDO::FETCH_ASSOC) ?: null;
  }
}

if (!$profileUser) {
  header('Location: /');
  exit;
}

$profileUserId = (int)($profileUser['id'] ?? 0);
$meId = (int)(is_array($me) ? ($me['id'] ?? 0) : 0);
$isOwner = ($meId > 0 && $meId === $profileUserId);
$isAdmin = ($meId > 0 && is_array($me)) ? (bool)is_admin($me) : false;

/* ===== Lang ===== */
$lang = (string)lang();
if (!in_array($lang, ['uk','ru','en'], true)) $lang = 'uk';
$T = function(string $uk, string $ru, string $en) use ($lang): string {
  if ($lang === 'ru') return $ru;
  if ($lang === 'en') return $en;
  return $uk;
};

if (!function_exists('profile_presence_meta')) {
  function profile_presence_meta(?string $lastSeenAt, callable $T, int $onlineWindowSec = 300): array
  {
    $raw = trim((string)$lastSeenAt);
    if ($raw === '') {
      return [false, $T('Не в мережі', 'Не в сети', 'Offline')];
    }

    $ts = strtotime($raw);
    if ($ts === false || $ts <= 0) {
      return [false, $T('Не в мережі', 'Не в сети', 'Offline')];
    }

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

    if ($diff <= $onlineWindowSec) {
      return [true, $T('Онлайн', 'Онлайн', 'Online')];
    }

    if ($diff < 3600) {
      $mins = max(1, (int)floor($diff / 60));
      return [false, sprintf($T('Був(ла) %d хв тому', 'Был(а) %d мин назад', 'Last seen %d min ago'), $mins)];
    }

    if ($diff < 86400) {
      return [false, sprintf($T('Був(ла) сьогодні о %s', 'Был(а) сегодня в %s', 'Last seen today at %s'), date('H:i', $ts))];
    }

    if ($diff < 172800) {
      return [false, sprintf($T('Був(ла) вчора о %s', 'Был(а) вчера в %s', 'Last seen yesterday at %s'), date('H:i', $ts))];
    }

    return [false, sprintf($T('Був(ла) %s', 'Был(а) %s', 'Last seen %s'), date('d.m.Y H:i', $ts))];
  }
}

if (!function_exists('profile_album_flash_text')) {
  function profile_album_flash_text(string $code, callable $T): array
  {
    return match ($code) {
      'created' => ['success', $T('Фотоальбом створено.', 'Фотоальбом создан.', 'Album created.')],
      'deleted' => ['success', $T('Фотоальбом видалено.', 'Фотоальбом удалён.', 'Album deleted.')],
      'title'   => ['warning', $T('Вкажіть назву фотоальбому.', 'Укажите название фотоальбома.', 'Enter the album title.')],
      'csrf'    => ['danger',  $T('Помилка безпеки (CSRF). Оновіть сторінку.', 'Ошибка безопасности (CSRF). Обновите страницу.', 'Security error (CSRF). Refresh the page.')],
      'db'      => ['danger',  $T('Помилка бази даних.', 'Ошибка базы данных.', 'Database error.')],
      'schema'  => ['danger',  $T('У БД не знайдено таблиці photo_albums / album_photos.', 'В БД не найдены таблицы photo_albums / album_photos.', 'Tables photo_albums / album_photos were not found.')],
      'denied'  => ['danger',  $T('Недостатньо прав для цієї дії.', 'Недостаточно прав для этого действия.', 'Access denied for this action.')],
      default   => ['', ''],
    };
  }
}

if (!function_exists('profile_album_date_text')) {
  function profile_album_date_text(?string $raw): string
  {
    $raw = trim((string)$raw);
    if ($raw === '') return '';
    $ts = strtotime($raw);
    if ($ts === false || $ts <= 0) return $raw;
    return date('d.m.Y H:i', $ts);
  }
}

/* ===== Friends/Follow lib ===== */
$friendsLib = __DIR__ . '/../functional/friends/_lib.php';
$friendsLibOk = is_file($friendsLib);
if ($friendsLibOk) {
  require_once $friendsLib;
}

/* ===== Relationship state ===== */
$friendsReady = false;
$areFriends = false;
$incomingPending = false; // він -> я
$outgoingPending = false; // я -> він
$outgoingDeclined = false; // я -> він declined
$isFollowing = false;
$fcsrf = '';

if (!$isOwner && $meId > 0 && $friendsLibOk && function_exists('vm_friends_ready')) {
  $friendsReady = vm_friends_ready($pdo);
  if ($friendsReady) {
    $areFriends = function_exists('vm_are_friends') ? vm_are_friends($pdo, $meId, $profileUserId) : false;

    try {
      $st = $pdo->prepare("
        SELECT from_user_id, to_user_id, status
        FROM friend_requests
        WHERE (from_user_id=? AND to_user_id=?)
           OR (from_user_id=? AND to_user_id=?)
        ORDER BY id DESC
        LIMIT 20
      ");
      $st->execute([$profileUserId, $meId, $meId, $profileUserId]);
      $rels = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
      foreach ($rels as $r) {
        $from = (int)($r['from_user_id'] ?? 0);
        $to   = (int)($r['to_user_id'] ?? 0);
        $stt  = (string)($r['status'] ?? '');

        if (!$incomingPending && $stt === 'pending' && $from === $profileUserId && $to === $meId) $incomingPending = true;
        if (!$outgoingPending && $stt === 'pending' && $from === $meId && $to === $profileUserId) $outgoingPending = true;
        if (!$outgoingDeclined && $stt === 'declined' && $from === $meId && $to === $profileUserId) $outgoingDeclined = true;

        if ($incomingPending && $outgoingPending && $outgoingDeclined) break;
      }
    } catch (Throwable $e) {
      $incomingPending = false;
      $outgoingPending = false;
      $outgoingDeclined = false;
    }

    $isFollowing = function_exists('vm_is_following') ? vm_is_following($pdo, $meId, $profileUserId) : false;
    $fcsrf = function_exists('vm_csrf_token') ? vm_csrf_token() : '';
  }
}

/* ===== Privacy support ===== */
$privacyCol = '';
$privacyCandidates = [
  'is_private',
  'private_profile',
  'profile_private',
  'closed_profile',
  'is_closed',
  'is_profile_private',
  'private',
];
foreach ($privacyCandidates as $col) {
  if (function_exists('db_has_column') && db_has_column($pdo, 'users', $col)) {
    $privacyCol = $col;
    break;
  }
}
$isPrivate = false;
if ($privacyCol !== '') {
  $isPrivate = ((int)($profileUser[$privacyCol] ?? 0) === 1);
}

/* ===== strict private profile behavior ===== */
$isPrivateStub = ($isPrivate && !$isOwner && !$isAdmin && !$areFriends);

if ($isPrivateStub && $meId <= 0) {
  header('Location: /login.php?to=' . urlencode(current_uri()));
  exit;
}

/* ===== View/Interact permissions ===== */
$canViewProfile = !$isPrivateStub;
$canInteract = ($meId > 0) && (
  $isOwner
  || $isAdmin
  || ($areFriends)
  || (!$isPrivate)
);

$profileTab = trim((string)($_GET['tab'] ?? 'posts'));
if (!in_array($profileTab, ['posts', 'friends', 'albums'], true)) {
  $profileTab = 'posts';
}

/* ===== Friend action flash ===== */
$relFlash = '';
if (isset($_GET['r']) && is_string($_GET['r']) && $_GET['r'] !== '') {
  $r = (string)$_GET['r'];
  $relFlash = match ($r) {
    'sent' => $T('Запит у друзі надіслано.', 'Заявка в друзья отправлена.', 'Friend request sent.'),
    'accepted' => $T('Ви стали друзями.', 'Вы стали друзьями.', 'You are now friends.'),
    'ok' => $T('Готово.', 'Готово.', 'Done.'),
    'already_friends' => $T('Ви вже друзі.', 'Вы уже друзья.', 'Already friends.'),
    'already_sent' => $T('Запит уже відправлено.', 'Заявка уже отправлена.', 'Request already sent.'),
    'friends_no_follow' => $T('Не можна підписатися, бо ви друзі.', 'Нельзя подписаться, вы друзья.', 'You can’t follow friends.'),
    'pending_no_follow' => $T('Не можна підписатися, поки є запит у друзі.', 'Нельзя подписаться, пока есть заявка.', 'You can’t follow while a friend request is pending.'),
    'already' => $T('Ви вже підписані.', 'Вы уже подписаны.', 'Already following.'),
    'no_pending' => $T('Немає активного запиту.', 'Нет активной заявки.', 'No active request.'),
    'not_friends' => $T('Ви не друзі.', 'Вы не друзья.', 'Not friends.'),
    'no' => $T('Ви не підписані.', 'Вы не подписаны.', 'Not following.'),
    'self' => $T('Неможливо виконати дію із собою.', 'Нельзя выполнить действие с собой.', 'You can’t do that to yourself.'),
    'csrf' => $T('Помилка безпеки (CSRF). Оновіть сторінку.', 'Ошибка безопасности (CSRF). Обновите страницу.', 'Security error (CSRF). Refresh the page.'),
    default => $T('Операцію виконано.', 'Операция выполнена.', 'Action completed.'),
  };
}

/* ===== helper: resolve avatar/cover url ===== */
if (!function_exists('resolve_profile_media_url')) {
  function resolve_profile_media_url(string $raw, string $username, string $type): string
  {
    $raw = trim($raw);
    $username = trim($username);
    $type = ($type === 'cover') ? 'cover' : 'avatar';
    if ($username === '') return '';

    $baseUrl = '/upload/' . $username . '/' . $type . '/';

    if ($raw !== '') {
      if (str_contains($raw, '..')) return '';
      if (preg_match('~^https?://~i', $raw)) return $raw;
      if (substr($raw, 0, 1) === '/') return $raw;

      if (preg_match('~^upload/~i', $raw) || preg_match('~^uploads/~i', $raw)) {
        $raw = ltrim($raw, '/');
        if (str_contains($raw, '..')) return '';
        return '/' . $raw;
      }

      $fn = basename($raw);
      if ($fn === '' || $fn === '.' || $fn === '..') return '';
      return $baseUrl . $fn;
    }

    return '';
  }
}

/* ===== Display name ===== */
$fullNameDb = trim((string)($profileUser['full_name'] ?? ''));
$first = trim((string)($profileUser['first_name'] ?? ''));
$last  = trim((string)($profileUser['last_name'] ?? ''));

$oldName = trim($first . ' ' . $last);

$profileDisplayName = $fullNameDb !== '' ? $fullNameDb : $oldName;
if ($profileDisplayName === '') $profileDisplayName = (string)($profileUser['username'] ?? '');

/* ===== Profile fields ===== */
$status    = (string)($profileUser['status'] ?? '');
$about     = (string)($profileUser['about'] ?? '');

$country   = trim((string)($profileUser['country'] ?? ''));
$city      = trim((string)($profileUser['city'] ?? ''));

$education = trim((string)($profileUser['education'] ?? ''));
$workplace = trim((string)($profileUser['workplace'] ?? ''));

$genderRaw = trim((string)($profileUser['gender'] ?? ''));
$genderLbl = '';
if ($genderRaw === 'f') $genderLbl = $T('Жіноча', 'Женский', 'Female');
elseif ($genderRaw === 'm') $genderLbl = $T('Чоловіча', 'Мужской', 'Male');

$birth = trim((string)($profileUser['birthdate'] ?? ($profileUser['birth_date'] ?? '')));

$profileUsername = (string)($profileUser['username'] ?? '');
$profileAvatarRaw = (string)($profileUser['avatar_path'] ?? '');
$profileCoverRaw  = (string)($profileUser['cover_path'] ?? '');

$profileAvatar = resolve_profile_media_url($profileAvatarRaw, $profileUsername, 'avatar');
$profileCover  = resolve_profile_media_url($profileCoverRaw,  $profileUsername, 'cover');

$profileInitials = user_initials($profileDisplayName, $profileUsername !== '' ? $profileUsername : 'U');

$lastSeenAt = trim((string)($profileUser['last_seen_at'] ?? ''));
[$profileIsOnline, $profilePresenceText] = profile_presence_meta($lastSeenAt, $T);

$profileNavParams = [];
if ($profileUsername !== '') {
  $profileNavParams['u'] = $profileUsername;
} elseif ($profileUserId > 0) {
  $profileNavParams['id'] = $profileUserId;
}
$currentLangParam = trim((string)($_GET['lang'] ?? ''));
if ($currentLangParam !== '' && in_array($currentLangParam, ['uk', 'ru', 'en'], true)) {
  $profileNavParams['lang'] = $currentLangParam;
}
$profileTabUrl = static function (string $tab) use ($profileNavParams): string {
  $params = $profileNavParams;
  $params['tab'] = $tab;
  return '/profile/index.php?' . http_build_query($params);
};

/* ===== Albums tab data ===== */
$albumsReady = false;
$albums = [];
$albumsFlashType = '';
$albumsFlashText = '';

if ($canViewProfile && $profileTab === 'albums') {
  [$albumsFlashType, $albumsFlashText] = profile_album_flash_text((string)($_GET['am'] ?? ''), $T);

  if ($albumsLibOk && function_exists('alb_ready')) {
    $albumsReady = alb_ready($pdo);
    if ($albumsReady && function_exists('alb_list_user_albums')) {
      $albums = alb_list_user_albums($pdo, $profileUserId, $me, 200, 0);
    }
  }
}

/* ===== SEO ===== */
$profileLabel = $T('Профіль', 'Профиль', 'Profile');
$title = trim($profileDisplayName) !== '' ? ($profileDisplayName . ' — ' . $profileLabel) : $profileLabel;

$loc = '';
if ($city !== '' && $country !== '') $loc = $city . ', ' . $country;
elseif ($city !== '') $loc = $city;
elseif ($country !== '') $loc = $country;

$meta_desc_parts = [];
if ($loc !== '') $meta_desc_parts[] = $loc;
if ($status !== '') $meta_desc_parts[] = $status;
$meta_desc = $meta_desc_parts ? implode(' • ', $meta_desc_parts) : $profileLabel;

$canonicalPath = '/profile/?u=' . rawurlencode($profileUsername !== '' ? $profileUsername : $viewUsername);
$canonical = function_exists('abs_url') ? abs_url($canonicalPath) : $canonicalPath;

$og_image = ($profileAvatar !== '') ? (function_exists('abs_url') ? abs_url($profileAvatar) : $profileAvatar) : '';

$seo_noindex = ($isPrivateStub) || ($viewUsername === '' && $viewUserId <= 0);
$meta_robots = $seo_noindex ? 'noindex, nofollow, noarchive, nosnippet' : 'index, follow';

require __DIR__ . '/../includes/header.php';

/* ===== repost support ===== */
$hasRepost = function_exists('db_has_column') ? db_has_column($pdo, 'posts', 'repost_post_id') : false;

/* ===== promoted post support ===== */
$hasPostIsPromoted = function_exists('db_has_column') ? db_has_column($pdo, 'posts', 'is_promoted') : false;
$hasPostPromotedCampaignId = function_exists('db_has_column') ? db_has_column($pdo, 'posts', 'promoted_campaign_id') : false;
$hasPostPromotedClickUrl = function_exists('db_has_column') ? db_has_column($pdo, 'posts', 'promoted_click_url') : false;

$postIsPromotedSel = $hasPostIsPromoted ? "p.is_promoted" : "0 AS is_promoted";
$postPromotedCampaignSel = $hasPostPromotedCampaignId ? "p.promoted_campaign_id" : "0 AS promoted_campaign_id";
$postPromotedClickUrlSel = $hasPostPromotedClickUrl ? "p.promoted_click_url" : "'' AS promoted_click_url";

/* ===== group posts support ===== */
$hasGroupId = function_exists('db_has_column') ? db_has_column($pdo, 'posts', 'group_id') : false;
$groupFilterSql = $hasGroupId ? " AND (p.group_id IS NULL OR p.group_id=0)" : "";

/* ===== Load posts only if can view profile ===== */
$posts = [];
$postIds = [];
$contentIds = [];

$attachmentsByPost = [];
$pollByPost = [];
$pollOptionsByPoll = [];
$pollVotesByOption = [];
$myPollVoteByPoll = [];

$commentsByPost = [];
$repliesByParent = [];
$commentAttById = [];
$commentIds = [];

$previewByHash = [];
$hashToUrl = [];

if ($canViewProfile && $profileTab === 'posts') {
  if ($hasRepost) {
    $sql = "
      SELECT
        p.id, p.user_id, p.repost_post_id, p.body, p.created_at,
        {$postIsPromotedSel},
        {$postPromotedCampaignSel},
        {$postPromotedClickUrlSel},
        u.username, u.first_name, u.last_name, u.avatar_path,

        op.id AS orig_id, op.user_id AS orig_user_id, op.body AS orig_body, op.created_at AS orig_created_at,
        ou.username AS orig_username, ou.first_name AS orig_first_name, ou.last_name AS orig_last_name, ou.avatar_path AS orig_avatar_path,

        COALESCE(rc.likes, 0) AS likes,
        COALESCE(rc.dislikes, 0) AS dislikes,
        mr.reaction AS my_reaction
      FROM posts p
      JOIN users u ON u.id = p.user_id
      LEFT JOIN posts op ON op.id = p.repost_post_id
      LEFT JOIN users ou ON ou.id = op.user_id
      LEFT JOIN (
        SELECT post_id,
               SUM(reaction='like') AS likes,
               SUM(reaction='dislike') AS dislikes
        FROM post_reactions
        GROUP BY post_id
      ) rc ON rc.post_id = p.id
      LEFT JOIN post_reactions mr
        ON mr.post_id = p.id AND mr.user_id = :me
      WHERE p.user_id = :uid
      {$groupFilterSql}
      ORDER BY p.id DESC
      LIMIT 50
    ";
  } else {
    $sql = "
      SELECT
        p.id, p.user_id, p.body, p.created_at,
        {$postIsPromotedSel},
        {$postPromotedCampaignSel},
        {$postPromotedClickUrlSel},
        u.username, u.first_name, u.last_name, u.avatar_path,
        COALESCE(rc.likes, 0) AS likes,
        COALESCE(rc.dislikes, 0) AS dislikes,
        mr.reaction AS my_reaction
      FROM posts p
      JOIN users u ON u.id = p.user_id
      LEFT JOIN (
        SELECT post_id,
               SUM(reaction='like') AS likes,
               SUM(reaction='dislike') AS dislikes
        FROM post_reactions
        GROUP BY post_id
      ) rc ON rc.post_id = p.id
      LEFT JOIN post_reactions mr
        ON mr.post_id = p.id AND mr.user_id = :me
      WHERE p.user_id = :uid
      {$groupFilterSql}
      ORDER BY p.id DESC
      LIMIT 50
    ";
  }

  $st = $pdo->prepare($sql);
  $st->execute([':me' => $meId, ':uid' => $profileUserId]);
  $posts = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];

  $postIds = array_values(array_filter(array_map(fn($r) => (int)($r['id'] ?? 0), $posts), fn($id) => $id > 0));

  if ($posts) {
    foreach ($posts as $p) {
      $pid = (int)($p['id'] ?? 0);
      if ($pid <= 0) continue;

      $cid = $pid;
      if ($hasRepost) {
        $rid = (int)($p['repost_post_id'] ?? 0);
        if ($rid > 0) $cid = $rid;
      }
      $contentIds[] = $cid;
    }
    $contentIds = array_values(array_unique(array_filter($contentIds, fn($id) => $id > 0)));
  }

  if ($contentIds) {
    $in = implode(',', array_fill(0, count($contentIds), '?'));
    $st = $pdo->prepare("SELECT * FROM post_attachments WHERE post_id IN ($in) ORDER BY id ASC");
    $st->execute($contentIds);
    $rows = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    foreach ($rows as $a) {
      $pid = (int)($a['post_id'] ?? 0);
      $attachmentsByPost[$pid][] = $a;
    }
  }

  $pollIds = [];
  if ($contentIds) {
    $in = implode(',', array_fill(0, count($contentIds), '?'));
    $st = $pdo->prepare("SELECT * FROM post_polls WHERE post_id IN ($in)");
    $st->execute($contentIds);
    $rows = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    foreach ($rows as $p) {
      $pollByPost[(int)($p['post_id'] ?? 0)] = $p;
      $pollIds[] = (int)($p['id'] ?? 0);
    }
  }

  if ($pollIds) {
    $pollIds = array_values(array_unique(array_filter($pollIds, fn($x) => $x > 0)));
    $in = implode(',', array_fill(0, count($pollIds), '?'));

    $st = $pdo->prepare("SELECT * FROM post_poll_options WHERE poll_id IN ($in) ORDER BY sort_order ASC, id ASC");
    $st->execute($pollIds);
    $opts = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    foreach ($opts as $o) {
      $pollOptionsByPoll[(int)($o['poll_id'] ?? 0)][] = $o;
    }

    $st = $pdo->prepare("SELECT option_id, COUNT(*) AS cnt FROM post_poll_votes WHERE poll_id IN ($in) GROUP BY option_id");
    $st->execute($pollIds);
    $vc = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    foreach ($vc as $r) {
      $pollVotesByOption[(int)($r['option_id'] ?? 0)] = (int)($r['cnt'] ?? 0);
    }

    if ($meId > 0) {
      $st = $pdo->prepare("SELECT poll_id, option_id FROM post_poll_votes WHERE user_id=? AND poll_id IN ($in)");
      $st->execute(array_merge([$meId], $pollIds));
      $mv = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
      foreach ($mv as $r) {
        $myPollVoteByPoll[(int)($r['poll_id'] ?? 0)] = (int)($r['option_id'] ?? 0);
      }
    }
  }

  if ($postIds) {
    $in = implode(',', array_fill(0, count($postIds), '?'));
    $sql = "
      SELECT
        c.id, c.post_id, c.user_id, c.parent_id, c.body, c.created_at,
        u.username, u.first_name, u.last_name, u.avatar_path,
        COALESCE(rc.likes, 0) AS likes,
        COALESCE(rc.dislikes, 0) AS dislikes,
        mr.reaction AS my_reaction
      FROM comments c
      JOIN users u ON u.id = c.user_id
      LEFT JOIN (
        SELECT comment_id,
               SUM(reaction='like') AS likes,
               SUM(reaction='dislike') AS dislikes
        FROM comment_reactions
        GROUP BY comment_id
      ) rc ON rc.comment_id = c.id
      LEFT JOIN comment_reactions mr
        ON mr.comment_id = c.id AND mr.user_id = ?
      WHERE c.post_id IN ($in)
      ORDER BY c.created_at ASC, c.id ASC
    ";
    $st = $pdo->prepare($sql);
    $st->execute(array_merge([$meId], $postIds));
    $rows = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];

    foreach ($rows as $c) {
      $cid = (int)($c['id'] ?? 0);
      if ($cid > 0) $commentIds[] = $cid;

      $pid = (int)($c['post_id'] ?? 0);
      $parent = (int)($c['parent_id'] ?? 0);

      if ($parent > 0) $repliesByParent[$parent][] = $c;
      else $commentsByPost[$pid][] = $c;
    }
  }

  if ($commentIds) {
    $commentIds = array_values(array_unique(array_filter($commentIds, fn($x) => $x > 0)));
    if ($commentIds) {
      $in = implode(',', array_fill(0, count($commentIds), '?'));
      $st = $pdo->prepare("SELECT * FROM comment_attachments WHERE comment_id IN ($in) ORDER BY id ASC");
      $st->execute($commentIds);
      $rows = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
      foreach ($rows as $a) {
        $cid = (int)($a['comment_id'] ?? 0);
        $commentAttById[$cid][] = $a;
      }
    }
  }

  /* ===== link previews for posts + comments ===== */
  if ((($posts && function_exists('db_has_table') && db_has_table($pdo, 'link_previews')) || ($commentIds && function_exists('db_has_table') && db_has_table($pdo, 'link_previews')))) {
    foreach ($posts as $p) {
      $txt = (string)($p['body'] ?? '');
      $u = extract_first_url($txt);
      $u = normalize_url($u);
      if ($u === '') continue;
      $hash = url_hash($u);
      $hashToUrl[$hash] = $u;
    }

    foreach ($commentsByPost as $list) {
      foreach ($list as $c) {
        $txt = (string)($c['body'] ?? '');
        $u = extract_first_url($txt);
        $u = normalize_url($u);
        if ($u === '') continue;
        $hash = url_hash($u);
        $hashToUrl[$hash] = $u;
      }
    }

    foreach ($repliesByParent as $list) {
      foreach ($list as $c) {
        $txt = (string)($c['body'] ?? '');
        $u = extract_first_url($txt);
        $u = normalize_url($u);
        if ($u === '') continue;
        $hash = url_hash($u);
        $hashToUrl[$hash] = $u;
      }
    }

    if ($hashToUrl) {
      $hashes = array_keys($hashToUrl);
      $in = implode(',', array_fill(0, count($hashes), '?'));
      $st = $pdo->prepare("SELECT url_hash, url, title, description, image, site_name FROM link_previews WHERE url_hash IN ($in)");
      $st->execute($hashes);
      $rows = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
      foreach ($rows as $r) {
        $previewByHash[(string)($r['url_hash'] ?? '')] = $r;
      }
    }
  }
}

/* ===== link preview card helper ===== */
if (!function_exists('render_link_preview_card')) {
  function render_link_preview_card(?array $p, string $url, string $hash): void
  {
    $title = trim((string)($p['title'] ?? ''));
    $desc  = trim((string)($p['description'] ?? ''));
    $img   = trim((string)($p['image'] ?? ''));
    $site  = trim((string)($p['site_name'] ?? ''));
    ?>
    <div class="lp-card-feed mt-3" data-lp-hash="<?= h($hash) ?>" data-lp-url="<?= h($url) ?>">
      <a class="lp-card-inner" href="<?= h($url) ?>" target="_blank" rel="noopener nofollow ugc">
        <div class="lp-img">
          <img loading="lazy" decoding="async" src="<?= h($img) ?>" alt="" <?= $img !== '' ? '' : 'style="display:none;"' ?>>
        </div>
        <div class="lp-meta">
          <div class="lp-title"><?= h($title !== '' ? $title : $url) ?></div>
          <?php if ($desc !== ''): ?>
            <div class="lp-desc"><?= h($desc) ?></div>
          <?php endif; ?>
          <?php if ($site !== ''): ?>
            <div class="lp-site"><?= h($site) ?></div>
          <?php endif; ?>
        </div>
      </a>
    </div>
    <?php
  }
}

/* ===== comment render helper ===== */
if (!function_exists('render_comment_profile')) {
  function render_comment_profile(
    array $c,
    array $repliesByParent,
    array $commentAttById,
    array $previewByHash,
    int $postId,
    int $meId,
    bool $isAdmin,
    bool $canInteract,
    callable $T,
    bool $isReply = false
  ): void
  {
    $cid = (int)($c['id'] ?? 0);
    $galleryId = 'c' . $cid;

    $likes = (int)($c['likes'] ?? 0);
    $dislikes = (int)($c['dislikes'] ?? 0);
    $myReaction = (string)($c['my_reaction'] ?? '');
    $atts = $commentAttById[$cid] ?? [];

    $authorId = (int)($c['user_id'] ?? 0);
    $canManage = ($meId > 0) && ($isAdmin || $meId === $authorId);

    $fullName = user_full_name($c);
    $username = (string)($c['username'] ?? '');
    $ava = user_avatar_path($c);
    $ini = user_initials($fullName, $username !== '' ? $username : 'U');

    $authorProfileUrl = $username !== ''
      ? ('/profile/index.php?u=' . rawurlencode($username))
      : (($authorId > 0) ? ('/profile/index.php?id=' . $authorId) : '');

    $confirmDel = $T('Видалити коментар?', 'Удалить комментарий?', 'Delete comment?');

    $imgs = array_values(array_filter($atts, fn($a) => ($a['file_type'] ?? '') === 'image'));
    $aud  = array_values(array_filter($atts, fn($a) => ($a['file_type'] ?? '') === 'audio'));
    $vid  = array_values(array_filter($atts, fn($a) => ($a['file_type'] ?? '') === 'video'));
    $fil  = array_values(array_filter($atts, fn($a) => ($a['file_type'] ?? '') === 'file'));

    $bodyText = (string)($c['body'] ?? '');
    $firstUrl = normalize_url(extract_first_url($bodyText));
    $firstHash = $firstUrl !== '' ? url_hash($firstUrl) : '';
    $lp = ($firstHash !== '' && isset($previewByHash[$firstHash])) ? $previewByHash[$firstHash] : null;

    $backToComment = current_uri() . '#comment-' . $cid;
    $likeBtnClass = ($myReaction === 'like') ? 'btn-success' : 'btn-outline-success';
    $disBtnClass  = ($myReaction === 'dislike') ? 'btn-danger' : 'btn-outline-danger';
    $likeTitle = $T('Лайків: ', 'Лайков: ', 'Likes: ') . $likes;
    $disTitle  = $T('Дизлайків: ', 'Дизлайков: ', 'Dislikes: ') . $dislikes;
    ?>
    <div class="comment <?= $isReply ? 'is-reply' : '' ?>" id="comment-<?= $cid ?>">
      <div class="comment-head d-flex justify-content-between align-items-start gap-2">
        <div class="d-flex align-items-center gap-2">
          <div class="vm-ava-sm">
            <?php if ($authorProfileUrl !== ''): ?><a href="<?= h($authorProfileUrl) ?>" class="comment-author-link-avatar"><?php endif; ?>
              <?php if ($ava !== ''): ?>
                <img src="<?= h($ava) ?>" alt="" loading="lazy">
              <?php else: ?>
                <div class="vm-ava-ph"><?= h($ini) ?></div>
              <?php endif; ?>
            <?php if ($authorProfileUrl !== ''): ?></a><?php endif; ?>
          </div>

          <div>
            <div class="comment-author">
              <?php if ($authorProfileUrl !== ''): ?>
                <a href="<?= h($authorProfileUrl) ?>" class="comment-author-link"><?= h($fullName) ?></a>
              <?php else: ?>
                <?= h($fullName) ?>
              <?php endif; ?>

              <?php if ($username !== ''): ?>
                <?php if ($authorProfileUrl !== ''): ?>
                  <a href="<?= h($authorProfileUrl) ?>" class="comment-author-link comment-author-username"> @<?= h($username) ?></a>
                <?php else: ?>
                  <span class="text-muted small"> @<?= h($username) ?></span>
                <?php endif; ?>
              <?php endif; ?>
            </div>
            <div class="comment-meta"><?= h((string)($c['created_at'] ?? '')) ?></div>
          </div>
        </div>

        <?php if ($canManage): ?>
          <details class="vm-menu">
            <summary class="vm-menu-btn" aria-label="menu">⋯</summary>
            <div class="vm-menu-box">
              <a class="vm-menu-item" href="/comment_edit.php?id=<?= $cid ?>&back=<?= urlencode(current_uri()) ?>">
                <?= h($T('Редагувати','Редактировать','Edit')) ?>
              </a>

              <form method="post" action="/functional/comment/manage.php"
                    onsubmit="return confirm(<?= json_encode($confirmDel, JSON_UNESCAPED_UNICODE) ?>);">
                <?= csrf_field() ?>
                <input type="hidden" name="action" value="delete">
                <input type="hidden" name="id" value="<?= $cid ?>">
                <input type="hidden" name="back" value="<?= h(current_uri()) ?>">
                <button type="submit" class="vm-menu-item vm-menu-danger">
                  <?= h($T('Видалити','Удалить','Delete')) ?>
                </button>
              </form>
            </div>
          </details>
        <?php endif; ?>
      </div>

      <?php if (trim($bodyText) !== ''): ?>
        <div class="comment-body"><?= linkify_text($bodyText) ?></div>
      <?php endif; ?>

      <?php if ($firstUrl !== '' && $firstHash !== ''): ?>
        <?php render_link_preview_card($lp, $firstUrl, $firstHash); ?>
      <?php endif; ?>

      <?php if ($atts): ?>
        <div class="comment-attachments mt-2" data-gallery-images="<?= h($galleryId) ?>">
          <?php if ($imgs): ?>
            <?php if (count($imgs) === 1): $a = $imgs[0]; ?>
              <div class="attachments-single">
                <a class="att-img att-img-single js-lightbox"
                   href="<?= h((string)($a['path'] ?? '')) ?>"
                   data-gallery="<?= h($galleryId) ?>"
                   target="_blank" rel="noopener">
                  <img src="<?= h((string)($a['path'] ?? '')) ?>" alt="" loading="lazy">
                </a>
              </div>
            <?php else: ?>
              <div class="attachments-grid">
                <?php foreach ($imgs as $a): ?>
                  <a class="att-img js-lightbox"
                     href="<?= h((string)($a['path'] ?? '')) ?>"
                     data-gallery="<?= h($galleryId) ?>"
                     target="_blank" rel="noopener">
                    <img src="<?= h((string)($a['path'] ?? '')) ?>" alt="" loading="lazy">
                  </a>
                <?php endforeach; ?>
              </div>
            <?php endif; ?>
          <?php endif; ?>

          <?php foreach ($aud as $a): ?>
            <div class="mt-2">
              <audio controls preload="none" class="w-100">
                <source src="<?= h((string)($a['path'] ?? '')) ?>" type="<?= h((string)($a['mime'] ?? '')) ?>">
              </audio>
            </div>
          <?php endforeach; ?>

          <?php foreach ($vid as $a): ?>
            <div class="mt-2">
              <video controls preload="metadata" class="w-100 rounded-3"
                     playsinline webkit-playsinline
                     disablepictureinpicture
                     controlslist="nodownload noplaybackrate">
                <source src="<?= h((string)($a['path'] ?? '')) ?>" type="<?= h((string)($a['mime'] ?? '')) ?>">
              </video>
            </div>
          <?php endforeach; ?>

          <?php if ($fil): ?>
            <div class="mt-2 d-flex flex-column gap-1">
              <?php foreach ($fil as $a): ?>
                <a class="att-file" href="<?= h((string)($a['path'] ?? '')) ?>" target="_blank" rel="noopener">
                  <?= h(t('download')) ?>: <?= h((string)($a['original_name'] ?? '')) ?>
                </a>
              <?php endforeach; ?>
            </div>
          <?php endif; ?>
        </div>
      <?php endif; ?>

      <div class="comment-actions mt-2 d-flex align-items-center gap-2">
        <?php if ($canInteract): ?>
          <form method="post" action="/comment_react.php" class="d-inline">
            <?= csrf_field() ?>
            <input type="hidden" name="comment_id" value="<?= $cid ?>">
            <input type="hidden" name="reaction" value="like">
            <input type="hidden" name="back" value="<?= h($backToComment) ?>">
            <button type="submit"
                    class="btn btn-sm <?= h($likeBtnClass) ?>"
                    data-comment="<?= $cid ?>" data-cmtreact="like"
                    title="<?= h($likeTitle) ?>"
                    aria-label="<?= h(t('like')) ?>">
              👍 <span class="count" id="clikes-<?= $cid ?>"><?= $likes ?></span>
            </button>
          </form>

          <form method="post" action="/comment_react.php" class="d-inline">
            <?= csrf_field() ?>
            <input type="hidden" name="comment_id" value="<?= $cid ?>">
            <input type="hidden" name="reaction" value="dislike">
            <input type="hidden" name="back" value="<?= h($backToComment) ?>">
            <button type="submit"
                    class="btn btn-sm <?= h($disBtnClass) ?>"
                    data-comment="<?= $cid ?>" data-cmtreact="dislike"
                    title="<?= h($disTitle) ?>"
                    aria-label="<?= h(t('dislike')) ?>">
              👎 <span class="count" id="cdislikes-<?= $cid ?>"><?= $dislikes ?></span>
            </button>
          </form>

          <button type="button" class="comment-reply-btn" data-reply-toggle="<?= $cid ?>"><?= h(t('reply')) ?></button>
        <?php else: ?>
          <button type="button" class="btn btn-sm btn-outline-success" disabled>
            👍 <span class="count"><?= $likes ?></span>
          </button>
          <button type="button" class="btn btn-sm btn-outline-danger" disabled>
            👎 <span class="count"><?= $dislikes ?></span>
          </button>
        <?php endif; ?>
      </div>

      <?php if ($canInteract): ?>
        <div class="comment-reply-form d-none" id="reply-form-<?= $cid ?>">
          <form method="post" action="/functional/comment/create.php" enctype="multipart/form-data" class="vstack gap-2 mt-2">
            <?= csrf_field() ?>
            <input type="hidden" name="post_id" value="<?= $postId ?>">
            <input type="hidden" name="parent_id" value="<?= $cid ?>">
            <input type="hidden" name="back" value="<?= h(current_uri() . '#comment-' . $cid) ?>">

            <div class="vm-emoji-wrap">
              <textarea class="form-control js-emoji-target" name="body" rows="2" placeholder="<?= h(t('write_comment')) ?>"></textarea>
            </div>

            <div class="d-flex flex-wrap gap-2 align-items-center justify-content-between">
              <label class="btn btn-sm btn-outline-secondary mb-0">
                <?= h(t('attach_files')) ?>
                <input type="file" name="files[]" multiple hidden
                       accept="image/*,audio/*,video/*,.pdf,.zip,.rar,.7z,.txt,.doc,.docx,.xls,.xlsx">
              </label>
              <div class="d-flex gap-2">
                <button class="btn btn-sm btn-primary" type="submit"><?= h(t('send')) ?></button>
                <button class="btn btn-sm btn-outline-secondary" type="button" data-reply-cancel="<?= $cid ?>"><?= h(t('cancel')) ?></button>
              </div>
            </div>
          </form>
        </div>
      <?php endif; ?>

      <?php
        $repls = $repliesByParent[$cid] ?? [];
        if ($repls):
      ?>
        <div class="comment-replies mt-2">
          <?php foreach ($repls as $r): ?>
            <?php render_comment_profile($r, $repliesByParent, $commentAttById, $previewByHash, $postId, $meId, $isAdmin, $canInteract, $T, true); ?>
          <?php endforeach; ?>
        </div>
      <?php endif; ?>
    </div>
    <?php
  }
}
?>

<style>
.vm-ava, .vm-ava-sm { width: 44px; height: 44px; border-radius: 999px; overflow: hidden; flex: 0 0 auto; }
.vm-ava-sm { width: 34px; height: 34px; }
.vm-ava img, .vm-ava-sm img { width: 100%; height: 100%; object-fit: cover; display:block; }
.vm-ava-ph { width:100%; height:100%; display:flex; align-items:center; justify-content:center; background:#e9ecef; color:#495057; font-weight:700; border-radius:999px; font-size:14px; }

.vm-menu { position:relative; }
.vm-menu-btn { list-style:none; cursor:pointer; user-select:none; border:0; background:transparent; padding:2px 6px; border-radius:8px; }
.vm-menu-btn::-webkit-details-marker { display:none; }
.vm-menu[open] .vm-menu-box { display:block; }
.vm-menu-box { display:none; position:absolute; right:0; top:24px; min-width:160px; background:#fff; border:1px solid rgba(0,0,0,.12); border-radius:12px; padding:6px; z-index:50; box-shadow:0 8px 24px rgba(0,0,0,.12); }
.vm-menu-item { display:block; width:100%; text-decoration:none; color:#212529; padding:8px 10px; border-radius:10px; }
.vm-menu-item:hover { background:#f1f3f5; }
.vm-menu-danger { color:#dc3545; background:transparent; border:0; text-align:left; }

.vm-repost-box { border:1px solid rgba(0,0,0,.08); border-radius:14px; padding:12px; background:#f8f9fa; }
.vm-repost-label { font-size: 12px; color:#6c757d; }

.comment-author-link,
.comment-author-link-avatar{
  color: inherit;
  text-decoration: none;
}
.comment-author-link:hover{
  text-decoration: underline;
}
.comment-author-username{
  color:#6c757d;
  font-size:.875em;
}

.profile-actions-bar .btn { border-radius:12px; }
.profile-actions-bar .badge { border-radius:999px; }

.vm-private-note { margin-top:8px; color:#6c757d; font-size:13px; }

.vm-sponsored-badge{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  padding:4px 11px;
  border-radius:999px;
  font-size:11px;
  font-weight:800;
  line-height:1;
  letter-spacing:.08em;
  text-transform:uppercase;
  white-space:nowrap;
  color:#f3fff8;
  background:linear-gradient(180deg,#1fc56f 0%,#0f9f56 100%);
  border:1px solid rgba(106,255,174,.95);
  box-shadow:
    0 0 0 1px rgba(11,90,48,.22) inset,
    0 0 10px rgba(44,255,157,.38),
    0 0 22px rgba(44,255,157,.20);
  text-shadow:0 0 10px rgba(255,255,255,.18);
}

.post-attachments video,
.comment-attachments video{
  display:block;
  width:100%;
  max-height:560px;
  height:auto;
  object-fit:contain;
  background:#000;
  border-radius:14px;
}
@media (max-width: 576px){
  .post-attachments video,
  .comment-attachments video{
    max-height:60vh;
  }
}

.lp-card-feed{ border:1px solid rgba(0,0,0,.12); border-radius:14px; overflow:hidden; background:#fff; }
.lp-card-feed .lp-card-inner{ display:flex; gap:12px; text-decoration:none; color:inherit; padding:12px; }
.lp-card-feed .lp-img{ width:110px; height:80px; border-radius:12px; overflow:hidden; flex:0 0 auto; background:#f1f3f5; }
.lp-card-feed .lp-img img{ width:100%; height:100%; object-fit:cover; display:block; }
.lp-card-feed .lp-meta{ min-width:0; }
.lp-card-feed .lp-title{ font-weight:700; line-height:1.2; margin-bottom:4px; }
.lp-card-feed .lp-desc{ color:#495057; font-size:13px; line-height:1.25; max-height:2.5em; overflow:hidden; }
.lp-card-feed .lp-site{ color:#6c757d; font-size:12px; margin-top:6px; }

.profile-avatar-link{
  display:block;
  width:100%;
  height:100%;
  color:inherit;
  text-decoration:none;
  cursor:zoom-in;
}
.profile-avatar-link img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
.profile-presence{
  display:inline-flex;
  align-items:center;
  gap:8px;
  margin-top:8px;
  font-size:14px;
}
.profile-presence-dot{
  width:10px;
  height:10px;
  border-radius:50%;
  flex:0 0 auto;
  box-shadow:0 0 0 2px rgba(255,255,255,.75);
}
.profile-presence-dot.is-online{
  background:#22c55e;
  box-shadow:0 0 0 2px rgba(255,255,255,.75), 0 0 12px rgba(34,197,94,.55);
}
.profile-presence-dot.is-offline{
  background:#9ca3af;
}
.profile-tabs-card{
  padding:10px 12px;
}
.profile-tabs{
  display:flex;
  flex-wrap:wrap;
  gap:10px;
}
.profile-tab-link{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:42px;
  padding:0 16px;
  border-radius:999px;
  border:1px solid rgba(148,163,184,.28);
  background:#fff;
  color:#334155;
  text-decoration:none;
  font-weight:600;
  transition:.15s ease;
}
.profile-tab-link:hover{
  background:#f8fafc;
  color:#0f172a;
}
.profile-tab-link.is-active{
  background:#2563eb;
  border-color:#2563eb;
  color:#fff;
  box-shadow:0 10px 26px rgba(37,99,235,.22);
}
.profile-section-placeholder{
  color:#6b7280;
  line-height:1.6;
}

/* ===== albums ===== */
.profile-albums-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:12px;
  flex-wrap:wrap;
}
.profile-albums-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(250px,1fr));
  gap:16px;
}
.profile-album-card{
  border:1px solid rgba(148,163,184,.18);
  border-radius:18px;
  background:#fff;
  overflow:hidden;
  box-shadow:0 10px 28px rgba(15,23,42,.05);
}
.profile-album-cover{
  display:block;
  width:100%;
  height:180px;
  background:linear-gradient(135deg,#eff6ff,#e2e8f0);
  overflow:hidden;
  text-decoration:none;
}
.profile-album-cover img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
.profile-album-cover-placeholder{
  width:100%;
  height:100%;
  display:flex;
  align-items:center;
  justify-content:center;
  color:#64748b;
  font-weight:700;
  letter-spacing:.02em;
}
.profile-album-body{
  padding:14px;
}
.profile-album-title{
  font-weight:700;
  line-height:1.25;
  margin-bottom:6px;
  color:#0f172a;
}
.profile-album-title a{
  color:inherit;
  text-decoration:none;
}
.profile-album-title a:hover{
  text-decoration:underline;
}
.profile-album-meta{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  margin-bottom:10px;
}
.profile-album-meta .badge{
  border-radius:999px;
  font-size:.78rem;
  padding:.48rem .68rem;
}
.profile-album-desc{
  color:#475569;
  font-size:.93rem;
  line-height:1.45;
  min-height:2.8em;
  white-space:pre-wrap;
  word-break:break-word;
}
.profile-album-actions{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  margin-top:12px;
}
.profile-album-create-card{
  border:1px solid rgba(148,163,184,.18);
  border-radius:18px;
  background:#fff;
  box-shadow:0 10px 28px rgba(15,23,42,.05);
}
.profile-album-empty{
  border:1px dashed rgba(148,163,184,.45);
  border-radius:16px;
  padding:28px;
  text-align:center;
  color:#64748b;
  background:#f8fafc;
}
@media (max-width: 576px){
  .profile-album-cover{ height:160px; }
}
</style>

<div class="feed-layout">
  <aside>
    <div class="sidebar-sticky">
      <?php require __DIR__ . '/../blocks/profile.php'; ?>
    </div>
  </aside>

  <section>
    <?php if ($relFlash !== ''): ?>
      <div class="alert alert-info"><?= h($relFlash) ?></div>
    <?php endif; ?>

    <?php require __DIR__ . '/partials/_hero.php'; ?>

    <?php require __DIR__ . '/partials/_tabs.php'; ?>

    <?php if ($me && $isOwner && $profileTab === 'posts' && $canViewProfile): ?>
      <?php
        $cp1 = __DIR__ . '/../blocks/create_post.php';
        if (is_file($cp1)) {
          $postAction = '/functional/post/create.php';
          $postBack   = current_uri();
          require $cp1;
        }
      ?>
    <?php endif; ?>

    <?php if ($isPrivateStub): ?>
      <div class="card card-app p-3 mb-3">
        <div class="fw-semibold mb-1"><?= h($T('Профіль закритий','Профиль закрыт','Profile is private')) ?></div>
        <div class="text-muted">
          <?= h($T(
            'Користувач закрив свій профіль. Доступні лише ПІБ та нікнейм. Ви можете надіслати запит у друзі.',
            'Пользователь закрыл свой профиль. Доступны только ФИО и никнейм. Вы можете отправить заявку в друзья.',
            'This user closed their profile. Only name and username are visible. You can send a friend request.'
          )) ?>
        </div>
      </div>

    <?php elseif (!$canViewProfile): ?>
      <div class="card card-app p-3 mb-3">
        <div class="fw-semibold mb-1"><?= h($T('Профіль закритий','Профиль закрыт','Profile is private')) ?></div>
        <div class="text-muted">
          <?= h($T(
            'Цей користувач закрив профіль.',
            'Пользователь закрыл профиль.',
            'This user has a private profile.'
          )) ?>
        </div>
      </div>

    <?php else: ?>

      <?php if ($profileTab === 'friends'): ?>
        <?php require __DIR__ . '/partials/_tab_friends.php'; ?>

      <?php elseif ($profileTab === 'albums'): ?>
        <?php require __DIR__ . '/partials/_tab_albums.php'; ?>
      <?php else: ?>

      <?php require __DIR__ . '/partials/_tab_posts.php'; ?>

      <?php require __DIR__ . '/partials/_posts_js.php'; ?>

      <?php endif; ?>

    <?php endif; ?>
  </section>

  <aside>
    <div class="sidebar-sticky">
      <?php require __DIR__ . '/../blocks/groups.php'; ?>
      <?php
        $gamesBlock = __DIR__ . '/../blocks/games.php';
        if (is_file($gamesBlock)) require $gamesBlock;
      ?>
    </div>
  </aside>
</div>

<?php
require __DIR__ . '/../includes/emoji_picker.php';
require __DIR__ . '/../includes/lightbox.php';
require __DIR__ . '/../includes/footer.php';
?>