<?php
declare(strict_types=1);

/**
 * /admin/index.php
 * Головний дашборд адмінпанелі:
 * - KPI (користувачі/пости/групи/коментарі)
 * - онлайн за 5 хв (через users.last_seen_at)
 * - розмір /upload (з кешем)
 * - трафік за день 00:00–23:59 Europe/Kyiv (якщо є traffic_hits)
 * - блок "Користувачі з України":
 *   - унікальні люди з UA
 *   - хіти з UA
 *   - area/line chart по днях
 *   - топ міст України
 *   - фільтрація за періодом (сьогодні / вчора / 7 / 14 / 30 днів / свій період)
 *
 * Функції файла:
 * - показує основні KPI мережі
 * - показує онлайн користувачів без залежності від timezone MySQL
 * - показує трафік людей/ботів
 * - показує динаміку українського трафіку по днях
 * - показує міста України, з яких заходять користувачі
 * - дає змогу фільтрувати український трафік за вибраний період
 */

require_once __DIR__ . '/../includes/start.php';
require_role(['admin']);

require_once __DIR__ . '/_helpers.php';
require_once __DIR__ . '/_sidebar.php';

$pdo = db();

$title = admin_tt('admin_dashboard', 'Адмінпанель', 'Админпанель', 'Admin panel');

/* =========================
   SEO: адмінка НЕ індексується
========================= */
$meta_robots = 'noindex, nofollow, noarchive, nosnippet';
$meta_desc   = '';
if (function_exists('abs_url')) {
    $canonical = abs_url('/admin/');
} else {
    $canonical = '/admin/';
}
if (!headers_sent()) {
    header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet', true);
}

/* ===== local helpers ===== */
if (!function_exists('admin_dash_max_int')) {
    function admin_dash_max_int(array $values, int $fallback = 1): int
    {
        $max = $fallback;
        foreach ($values as $v) {
            $n = (int)$v;
            if ($n > $max) $max = $n;
        }
        return max($fallback, $max);
    }
}

if (!function_exists('admin_dash_nice_max')) {
    function admin_dash_nice_max(int $max): int
    {
        $max = max(1, $max);
        if ($max <= 10) return 10;

        $pow = (int)pow(10, floor(log10((float)$max)));
        foreach ([1, 2, 5, 10] as $m) {
            $candidate = $pow * $m;
            if ($candidate >= $max) return (int)$candidate;
        }

        return (int)(ceil($max / 10) * 10);
    }
}

if (!function_exists('admin_dash_fmt_num')) {
    function admin_dash_fmt_num(float $n): string
    {
        return rtrim(rtrim(number_format($n, 2, '.', ''), '0'), '.');
    }
}

if (!function_exists('admin_dash_parse_ymd')) {
    function admin_dash_parse_ymd(?string $value, DateTimeZone $tz): ?DateTime
    {
        $value = trim((string)$value);
        if ($value === '' || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
            return null;
        }

        $dt = DateTime::createFromFormat('!Y-m-d', $value, $tz);
        if (!$dt) {
            return null;
        }

        $errors = DateTime::getLastErrors();
        if (is_array($errors) && (($errors['warning_count'] ?? 0) > 0 || ($errors['error_count'] ?? 0) > 0)) {
            return null;
        }

        return $dt;
    }
}

if (!function_exists('admin_dash_label_step')) {
    function admin_dash_label_step(int $count): int
    {
        $count = max(1, $count);
        if ($count <= 10) return 1;
        return (int)max(1, ceil($count / 10));
    }
}

if (!function_exists('admin_dash_svg_points')) {
    /**
     * @param array<int,array{day:string,label:string,uniq:int,hits:int}> $series
     * @return array<int,array{x:float,y:float,label:string,uniq:int,hits:int,day:string}>
     */
    function admin_dash_svg_points(
        array $series,
        int $svgW,
        int $svgH,
        int $padL,
        int $padR,
        int $padT,
        int $padB,
        int $maxY
    ): array {
        $count = count($series);
        if ($count <= 0) return [];

        $plotW = max(1, $svgW - $padL - $padR);
        $plotH = max(1, $svgH - $padT - $padB);

        $points = [];

        foreach ($series as $i => $row) {
            $x = ($count === 1)
                ? ($padL + ($plotW / 2))
                : ($padL + ($plotW * $i / ($count - 1)));

            $val = max(0, (int)($row['uniq'] ?? 0));
            $ratio = min(1, max(0, $val / max(1, $maxY)));
            $y = $padT + $plotH - ($plotH * $ratio);

            $points[] = [
                'x'     => (float)$x,
                'y'     => (float)$y,
                'label' => (string)($row['label'] ?? ''),
                'uniq'  => (int)($row['uniq'] ?? 0),
                'hits'  => (int)($row['hits'] ?? 0),
                'day'   => (string)($row['day'] ?? ''),
            ];
        }

        return $points;
    }
}

if (!function_exists('admin_dash_svg_smooth_path')) {
    /**
     * @param array<int,array{x:float,y:float}> $points
     */
    function admin_dash_svg_smooth_path(array $points): string
    {
        $count = count($points);
        if ($count === 0) return '';
        if ($count === 1) {
            return 'M ' . admin_dash_fmt_num($points[0]['x']) . ' ' . admin_dash_fmt_num($points[0]['y']);
        }

        $d = 'M ' . admin_dash_fmt_num($points[0]['x']) . ' ' . admin_dash_fmt_num($points[0]['y']);

        for ($i = 0; $i < $count - 1; $i++) {
            $p0 = $points[max(0, $i - 1)];
            $p1 = $points[$i];
            $p2 = $points[$i + 1];
            $p3 = $points[min($count - 1, $i + 2)];

            $cp1x = $p1['x'] + ($p2['x'] - $p0['x']) / 6;
            $cp1y = $p1['y'] + ($p2['y'] - $p0['y']) / 6;
            $cp2x = $p2['x'] - ($p3['x'] - $p1['x']) / 6;
            $cp2y = $p2['y'] - ($p3['y'] - $p1['y']) / 6;

            $d .= ' C '
                . admin_dash_fmt_num($cp1x) . ' ' . admin_dash_fmt_num($cp1y) . ', '
                . admin_dash_fmt_num($cp2x) . ' ' . admin_dash_fmt_num($cp2y) . ', '
                . admin_dash_fmt_num($p2['x']) . ' ' . admin_dash_fmt_num($p2['y']);
        }

        return $d;
    }
}

/* ===== KPI ===== */
$hasUsers    = admin_table_exists($pdo, 'users');
$hasPosts    = admin_table_exists($pdo, 'posts');
$hasGroups   = admin_table_exists($pdo, 'groups');
$hasComments = admin_table_exists($pdo, 'comments');

$totalUsers    = $hasUsers ? admin_safe_int($pdo, "SELECT COUNT(*) FROM users") : 0;
$totalPosts    = $hasPosts ? admin_safe_int($pdo, "SELECT COUNT(*) FROM posts") : 0;
$totalGroups   = $hasGroups ? admin_safe_int($pdo, "SELECT COUNT(*) FROM `groups`") : 0;
$totalComments = $hasComments ? admin_safe_int($pdo, "SELECT COUNT(*) FROM comments") : 0;

/* ===== time windows (Europe/Kyiv, без NOW() MySQL) ===== */
$tz = new DateTimeZone('Europe/Kyiv');
$nowKyiv = new DateTime('now', $tz);
$todayDate = $nowKyiv->format('Y-m-d');

$todayStart = $todayDate . ' 00:00:00';
$todayEnd   = $todayDate . ' 23:59:59';

$onlineSince = (clone $nowKyiv)->modify('-5 minutes')->format('Y-m-d H:i:s');

/* online users */
$onlineUsers = 0;
$onlineOk = $hasUsers && admin_column_exists($pdo, 'users', 'last_seen_at');
if ($onlineOk) {
    $onlineUsers = admin_safe_int(
        $pdo,
        "SELECT COUNT(*) FROM users WHERE last_seen_at IS NOT NULL AND last_seen_at >= ?",
        [$onlineSince]
    );
}

/* upload dir size */
$uploadPath = realpath(__DIR__ . '/../upload');
$uploadWeb  = '/upload/';
if ($uploadPath === false) {
    $uploadPath = realpath(__DIR__ . '/../uploads');
    $uploadWeb  = '/uploads/';
}
$uploadSize = ['bytes' => 0, 'truncated' => false, 'files' => 0, 'cached' => true];
$uploadOk = ($uploadPath !== false && is_dir($uploadPath));
if ($uploadOk) {
    $uploadSize = admin_dir_size_cached((string)$uploadPath, 'upload_size', 600);
}

/* traffic */
$hasTraffic = admin_table_exists($pdo, 'traffic_hits');
$hasVisitorId = $hasTraffic && admin_column_exists($pdo, 'traffic_hits', 'visitor_id');

/* ===== today traffic ===== */
$trafficNote = '';
$botsUnique = 0;
$botsHits = 0;
$humansUnique = 0;
$humansHits = 0;

$topBots = [];
$topCountries = [];
$topCities = [];

$uniqueExpr = $hasVisitorId
    ? "COUNT(DISTINCT COALESCE(NULLIF(visitor_id,''), ip))"
    : "COUNT(DISTINCT ip)";

if ($hasTraffic) {
    $botsHits = admin_safe_int(
        $pdo,
        "SELECT COUNT(*) FROM traffic_hits WHERE is_bot=1 AND created_at BETWEEN ? AND ?",
        [$todayStart, $todayEnd]
    );

    $humansHits = admin_safe_int(
        $pdo,
        "SELECT COUNT(*) FROM traffic_hits WHERE is_bot=0 AND created_at BETWEEN ? AND ?",
        [$todayStart, $todayEnd]
    );

    $humansUnique = admin_safe_int(
        $pdo,
        "SELECT {$uniqueExpr} FROM traffic_hits WHERE is_bot=0 AND created_at BETWEEN ? AND ?",
        [$todayStart, $todayEnd]
    );

    $botsUnique = admin_safe_int(
        $pdo,
        "SELECT COUNT(DISTINCT COALESCE(NULLIF(bot_name,''), NULLIF(ua,''), 'Unknown')) FROM traffic_hits WHERE is_bot=1 AND created_at BETWEEN ? AND ?",
        [$todayStart, $todayEnd]
    );

    try {
        $st = $pdo->prepare("
            SELECT COALESCE(NULLIF(bot_name,''),'Unknown') AS bot,
                   COUNT(*) AS hits,
                   MAX(created_at) AS last_seen
            FROM traffic_hits
            WHERE is_bot=1 AND created_at BETWEEN ? AND ?
            GROUP BY bot
            ORDER BY hits DESC
            LIMIT 10
        ");
        $st->execute([$todayStart, $todayEnd]);
        $topBots = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    } catch (Throwable $e) {
        $topBots = [];
    }

    try {
        $st = $pdo->prepare("
            SELECT COALESCE(NULLIF(country_code,''),'??') AS country,
                   COUNT(*) AS hits
            FROM traffic_hits
            WHERE is_bot=0 AND created_at BETWEEN ? AND ?
            GROUP BY COALESCE(NULLIF(country_code,''),'??')
            ORDER BY hits DESC
            LIMIT 10
        ");
        $st->execute([$todayStart, $todayEnd]);
        $topCountries = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    } catch (Throwable $e) {
        $topCountries = [];
    }

    try {
        $st = $pdo->prepare("
            SELECT COALESCE(NULLIF(city,''),'—') AS city,
                   COALESCE(NULLIF(country_code,''),'??') AS country,
                   COUNT(*) AS hits
            FROM traffic_hits
            WHERE is_bot=0 AND created_at BETWEEN ? AND ?
            GROUP BY COALESCE(NULLIF(city,''),'—'), COALESCE(NULLIF(country_code,''),'??')
            ORDER BY hits DESC
            LIMIT 10
        ");
        $st->execute([$todayStart, $todayEnd]);
        $topCities = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    } catch (Throwable $e) {
        $topCities = [];
    }

} else {
    $trafficNote = admin_tt(
        'admin_traffic_note',
        'Трафік/боти/країни з’являться після ввімкнення логування (таблиця traffic_hits).',
        'Трафик/боты/страны появятся после включения логирования (таблица traffic_hits).',
        'Traffic/bots/geo will appear after enabling logging (traffic_hits).'
    );
}

/* ===== Ukraine block: period filter ===== */
$uaPreset = trim((string)($_GET['ua_period'] ?? 'today'));
$uaAllowedPresets = ['today', 'yesterday', '7d', '14d', '30d', 'custom'];
if (!in_array($uaPreset, $uaAllowedPresets, true)) {
    $uaPreset = 'today';
}

$uaFromInput = trim((string)($_GET['ua_from'] ?? ''));
$uaToInput   = trim((string)($_GET['ua_to'] ?? ''));

$uaFilterStartDt = null;
$uaFilterEndDt   = null;
$uaMaxCustomDays = 90;

switch ($uaPreset) {
    case 'yesterday':
        $uaFilterStartDt = (clone $nowKyiv)->modify('-1 day')->setTime(0, 0, 0);
        $uaFilterEndDt   = (clone $nowKyiv)->modify('-1 day')->setTime(23, 59, 59);
        break;

    case '7d':
        $uaFilterStartDt = (clone $nowKyiv)->modify('-6 days')->setTime(0, 0, 0);
        $uaFilterEndDt   = (clone $nowKyiv)->setTime(23, 59, 59);
        break;

    case '14d':
        $uaFilterStartDt = (clone $nowKyiv)->modify('-13 days')->setTime(0, 0, 0);
        $uaFilterEndDt   = (clone $nowKyiv)->setTime(23, 59, 59);
        break;

    case '30d':
        $uaFilterStartDt = (clone $nowKyiv)->modify('-29 days')->setTime(0, 0, 0);
        $uaFilterEndDt   = (clone $nowKyiv)->setTime(23, 59, 59);
        break;

    case 'custom':
        $uaParsedFrom = admin_dash_parse_ymd($uaFromInput, $tz);
        $uaParsedTo   = admin_dash_parse_ymd($uaToInput, $tz);

        if ($uaParsedFrom instanceof DateTime && $uaParsedTo instanceof DateTime) {
            if ($uaParsedFrom > $uaParsedTo) {
                $tmp = $uaParsedFrom;
                $uaParsedFrom = $uaParsedTo;
                $uaParsedTo = $tmp;
            }

            $uaDiffDays = (int)$uaParsedFrom->diff($uaParsedTo)->days + 1;
            if ($uaDiffDays > $uaMaxCustomDays) {
                $uaParsedFrom = (clone $uaParsedTo)->modify('-' . ($uaMaxCustomDays - 1) . ' days');
            }

            $uaFilterStartDt = (clone $uaParsedFrom)->setTime(0, 0, 0);
            $uaFilterEndDt   = (clone $uaParsedTo)->setTime(23, 59, 59);
        } else {
            $uaPreset = 'today';
        }
        break;

    case 'today':
    default:
        $uaFilterStartDt = (clone $nowKyiv)->setTime(0, 0, 0);
        $uaFilterEndDt   = (clone $nowKyiv)->setTime(23, 59, 59);
        break;
}

if (!$uaFilterStartDt || !$uaFilterEndDt) {
    $uaPreset = 'today';
    $uaFilterStartDt = (clone $nowKyiv)->setTime(0, 0, 0);
    $uaFilterEndDt   = (clone $nowKyiv)->setTime(23, 59, 59);
}

$uaFilterStart = $uaFilterStartDt->format('Y-m-d H:i:s');
$uaFilterEnd   = $uaFilterEndDt->format('Y-m-d H:i:s');
$uaFilterDays  = (int)$uaFilterStartDt->diff($uaFilterEndDt)->days + 1;

$uaFormFromValue = $uaFilterStartDt->format('Y-m-d');
$uaFormToValue   = $uaFilterEndDt->format('Y-m-d');

$uaPeriodHuman = match ($uaPreset) {
    'yesterday' => admin_tt(
        'admin_ua_period_yesterday',
        'Вчора (' . $uaFilterStartDt->format('d.m.Y') . ')',
        'Вчера (' . $uaFilterStartDt->format('d.m.Y') . ')',
        'Yesterday (' . $uaFilterStartDt->format('d.m.Y') . ')'
    ),
    '7d' => admin_tt(
        'admin_ua_period_7d',
        'Останні 7 днів',
        'Последние 7 дней',
        'Last 7 days'
    ),
    '14d' => admin_tt(
        'admin_ua_period_14d',
        'Останні 14 днів',
        'Последние 14 дней',
        'Last 14 days'
    ),
    '30d' => admin_tt(
        'admin_ua_period_30d',
        'Останні 30 днів',
        'Последние 30 дней',
        'Last 30 days'
    ),
    'custom' => admin_tt(
        'admin_ua_period_custom',
        'Період: ' . $uaFilterStartDt->format('d.m.Y') . ' — ' . $uaFilterEndDt->format('d.m.Y'),
        'Период: ' . $uaFilterStartDt->format('d.m.Y') . ' — ' . $uaFilterEndDt->format('d.m.Y'),
        'Period: ' . $uaFilterStartDt->format('d.m.Y') . ' — ' . $uaFilterEndDt->format('d.m.Y')
    ),
    default => admin_tt(
        'admin_ua_period_today',
        'Сьогодні (' . $uaFilterStartDt->format('d.m.Y') . ')',
        'Сегодня (' . $uaFilterStartDt->format('d.m.Y') . ')',
        'Today (' . $uaFilterStartDt->format('d.m.Y') . ')'
    ),
};

$uaPeriodUnique = 0;
$uaPeriodHits   = 0;
$uaDailyMap     = [];
$uaDailySeries  = [];
$uaCities       = [];

if ($hasTraffic) {
    $uaPeriodUnique = admin_safe_int(
        $pdo,
        "SELECT {$uniqueExpr} FROM traffic_hits
         WHERE is_bot=0
           AND UPPER(COALESCE(country_code,''))='UA'
           AND created_at BETWEEN ? AND ?",
        [$uaFilterStart, $uaFilterEnd]
    );

    $uaPeriodHits = admin_safe_int(
        $pdo,
        "SELECT COUNT(*) FROM traffic_hits
         WHERE is_bot=0
           AND UPPER(COALESCE(country_code,''))='UA'
           AND created_at BETWEEN ? AND ?",
        [$uaFilterStart, $uaFilterEnd]
    );

    try {
        $st = $pdo->prepare("
            SELECT DATE(created_at) AS day_date,
                   {$uniqueExpr} AS uniq_visitors,
                   COUNT(*) AS hits
            FROM traffic_hits
            WHERE is_bot=0
              AND UPPER(COALESCE(country_code,''))='UA'
              AND created_at BETWEEN ? AND ?
            GROUP BY DATE(created_at)
            ORDER BY DATE(created_at) ASC
        ");
        $st->execute([$uaFilterStart, $uaFilterEnd]);
        foreach (($st->fetchAll(PDO::FETCH_ASSOC) ?: []) as $row) {
            $day = (string)($row['day_date'] ?? '');
            if ($day === '') continue;
            $uaDailyMap[$day] = [
                'uniq' => (int)($row['uniq_visitors'] ?? 0),
                'hits' => (int)($row['hits'] ?? 0),
            ];
        }
    } catch (Throwable $e) {
        $uaDailyMap = [];
    }

    for ($i = 0; $i < $uaFilterDays; $i++) {
        $dt = (clone $uaFilterStartDt)->modify('+' . $i . ' days');
        $day = $dt->format('Y-m-d');

        $uaDailySeries[] = [
            'day'   => $day,
            'label' => $dt->format('d.m'),
            'uniq'  => (int)($uaDailyMap[$day]['uniq'] ?? 0),
            'hits'  => (int)($uaDailyMap[$day]['hits'] ?? 0),
        ];
    }

    try {
        $st = $pdo->prepare("
            SELECT
                COALESCE(NULLIF(TRIM(city),''),'—') AS city_name,
                {$uniqueExpr} AS uniq_visitors,
                COUNT(*) AS hits
            FROM traffic_hits
            WHERE is_bot=0
              AND UPPER(COALESCE(country_code,''))='UA'
              AND created_at BETWEEN ? AND ?
            GROUP BY COALESCE(NULLIF(TRIM(city),''),'—')
            ORDER BY uniq_visitors DESC, hits DESC, city_name ASC
            LIMIT 15
        ");
        $st->execute([$uaFilterStart, $uaFilterEnd]);
        $uaCities = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
    } catch (Throwable $e) {
        $uaCities = [];
    }
}

$uaChartRawMax = admin_dash_max_int(array_map(static fn($r) => (int)($r['uniq'] ?? 0), $uaDailySeries), 1);
$uaChartMax = admin_dash_nice_max($uaChartRawMax);

$uaSvgW = 920;
$uaSvgH = 310;
$uaPadL = 52;
$uaPadR = 18;
$uaPadT = 18;
$uaPadB = 42;

$uaChartPoints = admin_dash_svg_points(
    $uaDailySeries,
    $uaSvgW,
    $uaSvgH,
    $uaPadL,
    $uaPadR,
    $uaPadT,
    $uaPadB,
    $uaChartMax
);

$uaLinePath = admin_dash_svg_smooth_path($uaChartPoints);

$uaBaseY = $uaSvgH - $uaPadB;
$uaAreaPath = '';
if ($uaChartPoints) {
    $firstPoint = $uaChartPoints[0];
    $lastPoint  = $uaChartPoints[count($uaChartPoints) - 1];
    $uaAreaPath = $uaLinePath
        . ' L ' . admin_dash_fmt_num($lastPoint['x']) . ' ' . admin_dash_fmt_num($uaBaseY)
        . ' L ' . admin_dash_fmt_num($firstPoint['x']) . ' ' . admin_dash_fmt_num($uaBaseY)
        . ' Z';
}

$uaTicks = [];
$uaTickCount = 5;
$uaPlotH = max(1, $uaSvgH - $uaPadT - $uaPadB);
for ($i = 0; $i <= $uaTickCount; $i++) {
    $ratio = $i / $uaTickCount;
    $y = $uaPadT + ($uaPlotH * $ratio);
    $value = (int)round($uaChartMax - ($uaChartMax * $ratio));
    $uaTicks[] = [
        'y'     => $y,
        'value' => $value,
    ];
}

$uaXLabelStep = admin_dash_label_step(count($uaChartPoints));

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

<style>
/* Локальні стилі лише для адмінки */
.admin-kpi .kpi-title{font-size:.85rem;color:rgba(0,0,0,.55)}
.admin-kpi .kpi-val{font-size:1.85rem;font-weight:800;line-height:1}
.admin-kpi .kpi-sub{font-size:.85rem;color:rgba(0,0,0,.55)}

.ua-mini-stat{
  border:1px solid rgba(0,0,0,.08);
  border-radius:14px;
  padding:12px 14px;
  background:#fff;
}
.ua-mini-stat .v{
  font-size:1.45rem;
  font-weight:800;
  line-height:1;
}
.ua-mini-stat .t{
  font-size:.82rem;
  color:rgba(0,0,0,.58);
}

.ua-filter-bar{
  display:flex;
  flex-wrap:wrap;
  align-items:flex-end;
  gap:12px;
  margin-bottom:14px;
  padding:12px;
  border:1px solid rgba(0,0,0,.08);
  border-radius:16px;
  background:#f8fafc;
}
.ua-filter-field{
  flex:1 1 170px;
  min-width:150px;
}
.ua-filter-field--preset{
  flex:1.4 1 220px;
}
.ua-filter-bar .form-label{
  margin-bottom:4px;
  font-size:.82rem;
  color:rgba(0,0,0,.62);
  font-weight:600;
}
.ua-filter-bar .form-select,
.ua-filter-bar .form-control{
  min-height:42px;
}
.ua-filter-actions{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:8px;
}
.ua-period-badge{
  display:inline-flex;
  align-items:center;
  gap:8px;
  padding:7px 12px;
  border-radius:999px;
  background:rgba(61,155,224,.10);
  color:#1d4f7a;
  font-size:.88rem;
  font-weight:700;
}

.ua-area-card{
  border:1px solid rgba(0,0,0,.08);
  border-radius:18px;
  background:#fff;
  padding:12px 12px 8px;
}

.ua-area-legend{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:10px;
  margin-bottom:8px;
  color:#5f6368;
  font-size:.95rem;
  font-weight:600;
}
.ua-area-legend-swatch{
  width:34px;
  height:14px;
  border:2px solid #3d9be0;
  background:rgba(61,155,224,.20);
  border-radius:0;
  box-shadow:inset 0 0 0 1px rgba(61,155,224,.08);
}

.ua-area-wrap{
  width:100%;
  overflow:hidden;
}

.ua-area-svg{
  width:100%;
  height:auto;
  display:block;
}

.ua-grid-line{
  stroke:rgba(0,0,0,.12);
  stroke-width:1;
}
.ua-grid-vert{
  stroke:rgba(0,0,0,.08);
  stroke-width:1;
}
.ua-axis-label{
  font-size:12px;
  fill:rgba(0,0,0,.65);
}
.ua-x-label{
  font-size:12px;
  fill:rgba(0,0,0,.65);
}
.ua-line{
  fill:none;
  stroke:#3d9be0;
  stroke-width:4;
  stroke-linecap:round;
  stroke-linejoin:round;
}
.ua-point{
  fill:#3d9be0;
  stroke:#3d9be0;
  stroke-width:1;
}
.ua-area-note{
  color:rgba(0,0,0,.58);
  font-size:.84rem;
  margin-top:8px;
}

@media (max-width: 991.98px){
  .ua-area-card{
    padding:10px 8px 6px;
  }
  .ua-filter-field,
  .ua-filter-field--preset{
    flex-basis:100%;
    min-width:100%;
  }
  .ua-filter-actions{
    width:100%;
  }
}
</style>

<div class="row g-3">
  <div class="col-lg-9">

    <div class="d-flex align-items-center justify-content-between mb-2">
      <h1 class="h4 mb-0"><?= h(admin_tt('admin_dashboard', 'Дашборд', 'Дашборд', 'Dashboard')) ?></h1>
      <div class="text-muted small">
        <?= h(admin_tt('admin_today', 'Сьогодні', 'Сегодня', 'Today')) ?>: <?= h($todayDate) ?>
      </div>
    </div>

    <div class="row g-3 admin-kpi mb-1">
      <div class="col-md-4">
        <div class="card card-app p-3">
          <div class="kpi-title"><?= h(admin_tt('admin_total_users', 'Зареєстровано користувачів', 'Зарегистрировано пользователей', 'Registered users')) ?></div>
          <div class="kpi-val"><?= (int)$totalUsers ?></div>
        </div>
      </div>

      <div class="col-md-4">
        <div class="card card-app p-3">
          <div class="kpi-title"><?= h(admin_tt('admin_online_users', 'Користувачів онлайн', 'Пользователей онлайн', 'Online users')) ?></div>
          <div class="kpi-val"><?= (int)$onlineUsers ?></div>
          <div class="kpi-sub">
            <?php if (!$onlineOk): ?>
              <?= h(admin_tt('admin_need_last_seen', 'Потрібно users.last_seen_at', 'Нужно users.last_seen_at', 'Need users.last_seen_at')) ?>
            <?php else: ?>
              <?= h(admin_tt('admin_last_5m', 'Активні за 5 хв', 'Активные за 5 мин', 'Active in 5 min')) ?>
            <?php endif; ?>
          </div>
        </div>
      </div>

      <div class="col-md-4">
        <div class="card card-app p-3">
          <div class="kpi-title"><?= h(admin_tt('admin_total_groups', 'Груп в мережі', 'Групп в сети', 'Groups')) ?></div>
          <div class="kpi-val"><?= (int)$totalGroups ?></div>
        </div>
      </div>

      <div class="col-md-4">
        <div class="card card-app p-3">
          <div class="kpi-title"><?= h(admin_tt('admin_total_posts', 'Постів', 'Постов', 'Posts')) ?></div>
          <div class="kpi-val"><?= (int)$totalPosts ?></div>
        </div>
      </div>

      <div class="col-md-4">
        <div class="card card-app p-3">
          <div class="kpi-title"><?= h(admin_tt('admin_total_comments', 'Коментарів', 'Комментариев', 'Comments')) ?></div>
          <div class="kpi-val"><?= (int)$totalComments ?></div>
        </div>
      </div>

      <div class="col-md-4">
        <div class="card card-app p-3">
          <div class="kpi-title"><?= h(admin_tt('admin_upload_size', 'Розмір папки', 'Размер папки', 'Folder size')) ?> <?= h($uploadWeb) ?></div>
          <div class="kpi-val"><?= $uploadOk ? h(admin_human_bytes((int)$uploadSize['bytes'])) : '—' ?></div>
          <div class="kpi-sub">
            <?php if ($uploadOk): ?>
              <?= h(admin_tt('admin_files', 'Файлів', 'Файлов', 'Files')) ?>: <?= (int)$uploadSize['files'] ?>
              <?php if (!empty($uploadSize['truncated'])): ?>
                · <?= h(admin_tt('admin_approx', 'приблизно', 'примерно', 'approx')) ?>
              <?php endif; ?>
              <?php if (!empty($uploadSize['cached'])): ?>
                · <?= h(admin_tt('admin_cached', 'кеш', 'кеш', 'cached')) ?>
              <?php endif; ?>
            <?php else: ?>
              <?= h(admin_tt('admin_upload_missing', 'Папка не знайдена', 'Папка не найдена', 'Folder not found')) ?>
            <?php endif; ?>
          </div>
        </div>
      </div>
    </div>

    <div class="row g-3 mt-0">
      <div class="col-md-6">
        <div class="card card-app p-3 h-100">
          <div class="d-flex align-items-center justify-content-between mb-2">
            <div class="fw-bold"><?= h(admin_tt('admin_today_bots', 'Роботи сьогодні', 'Боты сегодня', 'Bots today')) ?></div>
            <div class="text-muted small"><?= h($trafficNote) ?></div>
          </div>
          <div class="d-flex gap-3 align-items-end mb-3">
            <div>
              <div class="text-muted small"><?= h(admin_tt('admin_unique', 'Унікальних', 'Уникальных', 'Unique')) ?></div>
              <div class="display-6 fw-bold mb-0"><?= (int)$botsUnique ?></div>
            </div>
            <div>
              <div class="text-muted small"><?= h(admin_tt('admin_hits', 'Хітів', 'Хитов', 'Hits')) ?></div>
              <div class="display-6 fw-bold mb-0"><?= (int)$botsHits ?></div>
            </div>
          </div>

          <?php if ($hasTraffic): ?>
            <div class="table-responsive">
              <table class="table table-sm align-middle mb-0">
                <thead>
                  <tr>
                    <th><?= h(admin_tt('admin_bot', 'Робот', 'Бот', 'Bot')) ?></th>
                    <th class="text-end"><?= h(admin_tt('admin_hits', 'Хіти', 'Хиты', 'Hits')) ?></th>
                    <th class="text-end"><?= h(admin_tt('admin_last', 'Останній', 'Последний', 'Last')) ?></th>
                  </tr>
                </thead>
                <tbody>
                  <?php if (!$topBots): ?>
                    <tr><td colspan="3" class="text-muted small"><?= h(admin_tt('admin_no_data', 'Немає даних', 'Нет данных', 'No data')) ?></td></tr>
                  <?php else: ?>
                    <?php foreach ($topBots as $b): ?>
                      <tr>
                        <td><?= h((string)$b['bot']) ?></td>
                        <td class="text-end"><?= (int)$b['hits'] ?></td>
                        <td class="text-end text-muted small"><?= h((string)$b['last_seen']) ?></td>
                      </tr>
                    <?php endforeach; ?>
                  <?php endif; ?>
                </tbody>
              </table>
            </div>
          <?php endif; ?>
        </div>
      </div>

      <div class="col-md-6">
        <div class="card card-app p-3 h-100">
          <div class="fw-bold mb-2"><?= h(admin_tt('admin_today_people', 'Люди сьогодні', 'Люди сегодня', 'People today')) ?></div>

          <div class="d-flex gap-3 align-items-end mb-3">
            <div>
              <div class="text-muted small"><?= h(admin_tt('admin_unique', 'Унікальних', 'Уникальных', 'Unique')) ?></div>
              <div class="display-6 fw-bold mb-0"><?= (int)$humansUnique ?></div>
            </div>
            <div>
              <div class="text-muted small"><?= h(admin_tt('admin_hits', 'Хітів', 'Хитов', 'Hits')) ?></div>
              <div class="display-6 fw-bold mb-0"><?= (int)$humansHits ?></div>
            </div>
          </div>

          <?php if ($hasTraffic): ?>
            <div class="row g-3">
              <div class="col-6">
                <div class="text-muted small fw-bold mb-1"><?= h(admin_tt('admin_countries', 'Країни', 'Страны', 'Countries')) ?></div>
                <div class="table-responsive">
                  <table class="table table-sm mb-0">
                    <tbody>
                      <?php if (!$topCountries): ?>
                        <tr><td class="text-muted small"><?= h(admin_tt('admin_no_data', 'Немає даних', 'Нет данных', 'No data')) ?></td></tr>
                      <?php else: ?>
                        <?php foreach ($topCountries as $c): ?>
                          <tr>
                            <td><?= h((string)$c['country']) ?></td>
                            <td class="text-end"><?= (int)$c['hits'] ?></td>
                          </tr>
                        <?php endforeach; ?>
                      <?php endif; ?>
                    </tbody>
                  </table>
                </div>
              </div>

              <div class="col-6">
                <div class="text-muted small fw-bold mb-1"><?= h(admin_tt('admin_cities', 'Міста', 'Города', 'Cities')) ?></div>
                <div class="table-responsive">
                  <table class="table table-sm mb-0">
                    <tbody>
                      <?php if (!$topCities): ?>
                        <tr><td class="text-muted small"><?= h(admin_tt('admin_no_data', 'Немає даних', 'Нет данных', 'No data')) ?></td></tr>
                      <?php else: ?>
                        <?php foreach ($topCities as $c): ?>
                          <tr>
                            <td><?= h((string)$c['city']) ?> <span class="text-muted small">(<?= h((string)$c['country']) ?>)</span></td>
                            <td class="text-end"><?= (int)$c['hits'] ?></td>
                          </tr>
                        <?php endforeach; ?>
                      <?php endif; ?>
                    </tbody>
                  </table>
                </div>
              </div>
            </div>
          <?php endif; ?>
        </div>
      </div>
    </div>

    <div class="row g-3 mt-0">
      <div class="col-12">
        <div class="card card-app p-3">
          <div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-3">
            <div>
              <div class="fw-bold"><?= h(admin_tt('admin_ua_users', 'Користувачі з України', 'Пользователи из Украины', 'Users from Ukraine')) ?></div>
              <div class="text-muted small">
                <?= h(admin_tt(
                  'admin_ua_block_note',
                  'Дані тільки по людях (не ботах). Можна вибрати будь-який період.',
                  'Данные только по людям (не ботам). Можно выбрать любой период.',
                  'Humans only (no bots). You can choose any period.'
                )) ?>
              </div>
            </div>
            <div class="ua-period-badge">
              <?= h($uaPeriodHuman) ?>
            </div>
          </div>

          <form method="get" action="/admin/" class="ua-filter-bar">
            <div class="ua-filter-field ua-filter-field--preset">
              <label class="form-label" for="ua_period"><?= h(admin_tt('admin_ua_filter_period', 'Період', 'Период', 'Period')) ?></label>
              <select class="form-select" name="ua_period" id="ua_period">
                <option value="today" <?= $uaPreset === 'today' ? 'selected' : '' ?>><?= h(admin_tt('admin_ua_filter_today', 'Сьогодні', 'Сегодня', 'Today')) ?></option>
                <option value="yesterday" <?= $uaPreset === 'yesterday' ? 'selected' : '' ?>><?= h(admin_tt('admin_ua_filter_yesterday', 'Вчора', 'Вчера', 'Yesterday')) ?></option>
                <option value="7d" <?= $uaPreset === '7d' ? 'selected' : '' ?>><?= h(admin_tt('admin_ua_filter_7d', 'Останні 7 днів', 'Последние 7 дней', 'Last 7 days')) ?></option>
                <option value="14d" <?= $uaPreset === '14d' ? 'selected' : '' ?>><?= h(admin_tt('admin_ua_filter_14d', 'Останні 14 днів', 'Последние 14 дней', 'Last 14 days')) ?></option>
                <option value="30d" <?= $uaPreset === '30d' ? 'selected' : '' ?>><?= h(admin_tt('admin_ua_filter_30d', 'Останні 30 днів', 'Последние 30 дней', 'Last 30 days')) ?></option>
                <option value="custom" <?= $uaPreset === 'custom' ? 'selected' : '' ?>><?= h(admin_tt('admin_ua_filter_custom', 'Свій період', 'Свой период', 'Custom range')) ?></option>
              </select>
            </div>

            <div class="ua-filter-field">
              <label class="form-label" for="ua_from"><?= h(admin_tt('admin_ua_filter_from', 'Від', 'От', 'From')) ?></label>
              <input
                type="date"
                class="form-control"
                name="ua_from"
                id="ua_from"
                value="<?= h($uaFormFromValue) ?>"
                <?= $uaPreset !== 'custom' ? 'disabled' : '' ?>
              >
            </div>

            <div class="ua-filter-field">
              <label class="form-label" for="ua_to"><?= h(admin_tt('admin_ua_filter_to', 'До', 'До', 'To')) ?></label>
              <input
                type="date"
                class="form-control"
                name="ua_to"
                id="ua_to"
                value="<?= h($uaFormToValue) ?>"
                <?= $uaPreset !== 'custom' ? 'disabled' : '' ?>
              >
            </div>

            <div class="ua-filter-actions">
              <button type="submit" class="btn btn-primary">
                <?= h(admin_tt('admin_ua_filter_show', 'Показати', 'Показать', 'Show')) ?>
              </button>
              <a href="/admin/" class="btn btn-outline-secondary">
                <?= h(admin_tt('admin_ua_filter_reset', 'Скинути', 'Сбросить', 'Reset')) ?>
              </a>
            </div>
          </form>

          <?php if (!$hasTraffic): ?>
            <div class="text-muted small mb-3"><?= h($trafficNote) ?></div>
          <?php endif; ?>

          <div class="row g-3 mb-3">
            <div class="col-md-3">
              <div class="ua-mini-stat h-100">
                <div class="t"><?= h(admin_tt('admin_ua_period_unique', 'Унікальних за період', 'Уникальных за период', 'Unique in period')) ?></div>
                <div class="v mt-1"><?= (int)$uaPeriodUnique ?></div>
              </div>
            </div>
            <div class="col-md-3">
              <div class="ua-mini-stat h-100">
                <div class="t"><?= h(admin_tt('admin_ua_period_hits', 'Хітів за період', 'Хитов за период', 'Hits in period')) ?></div>
                <div class="v mt-1"><?= (int)$uaPeriodHits ?></div>
              </div>
            </div>
            <div class="col-md-3">
              <div class="ua-mini-stat h-100">
                <div class="t"><?= h(admin_tt('admin_ua_period_days', 'Днів у періоді', 'Дней в периоде', 'Days in period')) ?></div>
                <div class="v mt-1"><?= (int)$uaFilterDays ?></div>
              </div>
            </div>
            <div class="col-md-3">
              <div class="ua-mini-stat h-100">
                <div class="t"><?= h(admin_tt('admin_ua_top_cities_count', 'Міст у вибірці', 'Городов в выборке', 'Cities in sample')) ?></div>
                <div class="v mt-1"><?= count($uaCities) ?></div>
              </div>
            </div>
          </div>

          <div class="row g-3">
            <div class="col-lg-8">
              <div class="fw-semibold mb-2"><?= h(admin_tt('admin_ua_daily_chart', 'Динаміка по днях', 'Динамика по дням', 'Daily dynamics')) ?></div>

              <?php if (!$hasTraffic): ?>
                <div class="text-muted small"><?= h(admin_tt('admin_no_data', 'Немає даних', 'Нет данных', 'No data')) ?></div>
              <?php else: ?>
                <div class="ua-area-card">
                  <div class="ua-area-legend">
                    <span class="ua-area-legend-swatch"></span>
                    <span><?= h(admin_tt('admin_ua_uniq_per_day', 'Унікальні / день', 'Уникальные / день', 'Unique / day')) ?></span>
                  </div>

                  <div class="ua-area-wrap">
                    <svg class="ua-area-svg" viewBox="0 0 <?= (int)$uaSvgW ?> <?= (int)$uaSvgH ?>" preserveAspectRatio="none" role="img" aria-label="<?= h(admin_tt('admin_ua_daily_chart', 'Динаміка по днях', 'Динамика по дням', 'Daily dynamics')) ?>">
                      <defs>
                        <linearGradient id="uaAreaGradient" x1="0" y1="0" x2="0" y2="1">
                          <stop offset="0%" stop-color="#3d9be0" stop-opacity="0.55"></stop>
                          <stop offset="100%" stop-color="#3d9be0" stop-opacity="0.18"></stop>
                        </linearGradient>
                      </defs>

                      <?php foreach ($uaTicks as $tick): ?>
                        <line
                          class="ua-grid-line"
                          x1="<?= admin_dash_fmt_num($uaPadL) ?>"
                          y1="<?= admin_dash_fmt_num((float)$tick['y']) ?>"
                          x2="<?= admin_dash_fmt_num($uaSvgW - $uaPadR) ?>"
                          y2="<?= admin_dash_fmt_num((float)$tick['y']) ?>"
                        ></line>
                        <text
                          class="ua-axis-label"
                          x="<?= admin_dash_fmt_num($uaPadL - 8) ?>"
                          y="<?= admin_dash_fmt_num((float)$tick['y'] + 4) ?>"
                          text-anchor="end"
                        ><?= (int)$tick['value'] ?></text>
                      <?php endforeach; ?>

                      <?php foreach ($uaChartPoints as $pt): ?>
                        <line
                          class="ua-grid-vert"
                          x1="<?= admin_dash_fmt_num($pt['x']) ?>"
                          y1="<?= admin_dash_fmt_num($uaPadT) ?>"
                          x2="<?= admin_dash_fmt_num($pt['x']) ?>"
                          y2="<?= admin_dash_fmt_num($uaBaseY) ?>"
                        ></line>
                      <?php endforeach; ?>

                      <?php if ($uaAreaPath !== ''): ?>
                        <path d="<?= h($uaAreaPath) ?>" fill="url(#uaAreaGradient)" stroke="none"></path>
                      <?php endif; ?>

                      <?php if ($uaLinePath !== ''): ?>
                        <path class="ua-line" d="<?= h($uaLinePath) ?>"></path>
                      <?php endif; ?>

                      <?php foreach ($uaChartPoints as $i => $pt): ?>
                        <circle
                          class="ua-point"
                          cx="<?= admin_dash_fmt_num($pt['x']) ?>"
                          cy="<?= admin_dash_fmt_num($pt['y']) ?>"
                          r="3.2"
                        >
                          <title><?= h($pt['day'] . ' — ' . admin_tt('admin_unique', 'Унікальні', 'Уникальные', 'Unique') . ': ' . $pt['uniq'] . '; ' . admin_tt('admin_hits', 'Хіти', 'Хиты', 'Hits') . ': ' . $pt['hits']) ?></title>
                        </circle>

                        <?php if ($i % $uaXLabelStep === 0 || $i === count($uaChartPoints) - 1): ?>
                          <text
                            class="ua-x-label"
                            x="<?= admin_dash_fmt_num($pt['x']) ?>"
                            y="<?= admin_dash_fmt_num($uaSvgH - 14) ?>"
                            text-anchor="middle"
                          ><?= h($pt['label']) ?></text>
                        <?php endif; ?>
                      <?php endforeach; ?>
                    </svg>
                  </div>
                </div>

                <div class="ua-area-note">
                  <?= h(admin_tt(
                    'admin_ua_chart_note',
                    'Графік показує унікальних користувачів/відвідувачів з України за кожен день у вибраному періоді.',
                    'График показывает уникальных пользователей/посетителей из Украины за каждый день в выбранном периоде.',
                    'The chart shows unique users/visitors from Ukraine for each day in the selected period.'
                  )) ?>
                </div>
              <?php endif; ?>
            </div>

            <div class="col-lg-4">
              <div class="fw-semibold mb-2"><?= h(admin_tt('admin_ua_cities', 'Міста України', 'Города Украины', 'Cities of Ukraine')) ?></div>
              <div class="table-responsive">
                <table class="table table-sm align-middle mb-0">
                  <thead>
                    <tr>
                      <th><?= h(admin_tt('admin_city', 'Місто', 'Город', 'City')) ?></th>
                      <th class="text-end"><?= h(admin_tt('admin_unique', 'Унік.', 'Уник.', 'Uniq.')) ?></th>
                      <th class="text-end"><?= h(admin_tt('admin_hits', 'Хіти', 'Хиты', 'Hits')) ?></th>
                    </tr>
                  </thead>
                  <tbody>
                    <?php if (!$uaCities): ?>
                      <tr>
                        <td colspan="3" class="text-muted small"><?= h(admin_tt('admin_no_data', 'Немає даних', 'Нет данных', 'No data')) ?></td>
                      </tr>
                    <?php else: ?>
                      <?php foreach ($uaCities as $row): ?>
                        <tr>
                          <td><?= h((string)$row['city_name']) ?></td>
                          <td class="text-end"><?= (int)($row['uniq_visitors'] ?? 0) ?></td>
                          <td class="text-end"><?= (int)($row['hits'] ?? 0) ?></td>
                        </tr>
                      <?php endforeach; ?>
                    <?php endif; ?>
                  </tbody>
                </table>
              </div>
              <div class="text-muted small mt-2">
                <?= h(admin_tt(
                  'admin_ua_cities_note',
                  'Топ міст за вибраний період.',
                  'Топ городов за выбранный период.',
                  'Top cities for the selected period.'
                )) ?>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

  </div>

  <div class="col-lg-3">
    <?php admin_sidebar('dashboard'); ?>
  </div>
</div>

<script>
(function () {
  var period = document.getElementById('ua_period');
  var from = document.getElementById('ua_from');
  var to = document.getElementById('ua_to');

  if (!period || !from || !to) return;

  function syncCustomState() {
    var isCustom = period.value === 'custom';
    from.disabled = !isCustom;
    to.disabled = !isCustom;
  }

  period.addEventListener('change', syncCustomState);
  syncCustomState();
})();
</script>

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