<?php
// Log Dashboard — visitor/request log viewer, admin-only (Motaher). Reads
// visitor_log, written to by includes/visitor_log.php's log_visit() call
// near the top of every page. Same filter/paginate shape as expenses.php,
// since that pattern is already proven here.
//
// Time column: visited_at is stored in the app's canonical timezone
// (Asia/Shanghai — see config.php). The server renders that as a fallback
// (works with JS off), but each cell also carries the same instant as an
// explicit-offset ISO 8601 string in data-visited-at; app.js reformats
// that client-side into whichever timezone the viewing browser is
// currently in, so the displayed time always matches wherever the admin
// happens to be right now, not a fixed server timezone.
require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/visitor_log.php';
log_visit();
require_login();
require_admin(); // Log Dashboard is Motaher-only.

$db = get_db();

$search = trim((string) ($_GET['search'] ?? ''));
$dateFrom = trim((string) ($_GET['date_from'] ?? ''));
$dateTo = trim((string) ($_GET['date_to'] ?? ''));
$page = max(1, (int) ($_GET['page'] ?? 1));
$perPage = 50;

if ($dateFrom !== '' && DateTime::createFromFormat('Y-m-d', $dateFrom) === false) {
    $dateFrom = '';
}
if ($dateTo !== '' && DateTime::createFromFormat('Y-m-d', $dateTo) === false) {
    $dateTo = '';
}

$where = [];
$params = [];

if ($search !== '') {
    $where[] = '(page LIKE :search OR ip LIKE :search OR country LIKE :search OR city LIKE :search)';
    $params['search'] = '%' . $search . '%';
}
if ($dateFrom !== '') {
    $where[] = 'visited_at >= :date_from';
    $params['date_from'] = $dateFrom . ' 00:00:00';
}
if ($dateTo !== '') {
    $where[] = 'visited_at <= :date_to';
    $params['date_to'] = $dateTo . ' 23:59:59';
}

$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';

$totalsStmt = $db->prepare("SELECT COUNT(*) AS cnt, COUNT(DISTINCT ip) AS unique_ips FROM visitor_log $whereSql");
$totalsStmt->execute($params);
$totals = $totalsStmt->fetch();
$totalCount = (int) $totals['cnt'];
$uniqueIps = (int) $totals['unique_ips'];

$todayStmt = $db->prepare('SELECT COUNT(*) FROM visitor_log WHERE visited_at >= :today_start');
$todayStmt->execute(['today_start' => date('Y-m-d') . ' 00:00:00']);
$todayCount = (int) $todayStmt->fetchColumn();

$totalPages = max(1, (int) ceil($totalCount / $perPage));
$page = min($page, $totalPages);
$offset = ($page - 1) * $perPage;

$listStmt = $db->prepare(
    "SELECT id, ip, country, region, city, isp, page, referrer, browser, os, device, language, visited_at
     FROM visitor_log
     $whereSql
     ORDER BY visited_at DESC, id DESC
     LIMIT $perPage OFFSET $offset"
);
$listStmt->execute($params);
$results = $listStmt->fetchAll();

$hasFilters = $search !== '' || $dateFrom !== '' || $dateTo !== '';

/** Builds a query string from the current filters, with overrides (used for pagination links). */
function log_filters_query_string(array $current, array $overrides = []): string
{
    $merged = array_filter(array_merge($current, $overrides), fn ($v) => $v !== '' && $v !== 0 && $v !== null);

    return http_build_query($merged);
}

$currentFilters = [
    'search'    => $search,
    'date_from' => $dateFrom,
    'date_to'   => $dateTo,
    'page'      => $page,
];

$pageTitle = 'Log Dashboard';
$currentPage = 'log_dashboard';
require __DIR__ . '/includes/layout/header.php';
?>

<div class="row g-3 g-lg-4 mb-3 mb-lg-4">
  <div class="col-6 col-lg-3">
    <section class="card-x p-3" aria-label="Total visits">
      <div class="text-secondary small">Total visits</div>
      <div class="fs-4 fw-bold tnum"><?= e((string) $totalCount) ?></div>
    </section>
  </div>
  <div class="col-6 col-lg-3">
    <section class="card-x p-3" aria-label="Unique IPs">
      <div class="text-secondary small">Unique IPs</div>
      <div class="fs-4 fw-bold tnum"><?= e((string) $uniqueIps) ?></div>
    </section>
  </div>
  <div class="col-6 col-lg-3">
    <section class="card-x p-3" aria-label="Today">
      <div class="text-secondary small">Today</div>
      <div class="fs-4 fw-bold tnum"><?= e((string) $todayCount) ?></div>
    </section>
  </div>
</div>

<section class="card-x p-3 p-lg-4 mb-3 mb-lg-4" aria-label="Filter log">
  <form method="get" class="row g-2 align-items-end">
    <div class="col-12 col-md-4">
      <label class="field-label mt-0" for="search">Search</label>
      <input class="form-control" type="text" id="search" name="search" value="<?= e($search) ?>" placeholder="page, IP, country, city">
    </div>
    <div class="col-6 col-md-3">
      <label class="field-label mt-0" for="date_from">From</label>
      <input class="form-control" type="date" id="date_from" name="date_from" value="<?= e($dateFrom) ?>">
    </div>
    <div class="col-6 col-md-3">
      <label class="field-label mt-0" for="date_to">To</label>
      <input class="form-control" type="date" id="date_to" name="date_to" value="<?= e($dateTo) ?>">
    </div>
    <div class="col-12 col-md-2 d-flex gap-2">
      <button class="btn-accent flex-grow-1" type="submit">Filter</button>
      <?php if ($hasFilters): ?>
        <a class="btn btn-outline-secondary" href="log_dashboard.php" aria-label="Clear filters"><i class="bi bi-x-lg"></i></a>
      <?php endif; ?>
    </div>
  </form>
</section>

<section class="card-x p-3 p-lg-4" aria-label="Visitor log">
  <div class="d-flex align-items-baseline justify-content-between mb-2 flex-wrap gap-1">
    <div class="sec-title tnum"><?= e((string) $totalCount) ?> <?= $totalCount === 1 ? 'visit' : 'visits' ?></div>
    <?php if ($totalPages > 1): ?>
      <div class="sec-sub">Page <?= e((string) $page) ?> of <?= e((string) $totalPages) ?></div>
    <?php endif; ?>
  </div>

  <?php if (!$results): ?>
    <p class="text-secondary small mb-0">No visits match these filters.</p>
  <?php else: ?>
    <div class="table-responsive">
      <table class="table table-sm align-middle mb-0">
        <thead>
          <tr class="text-secondary small">
            <th>Time</th>
            <th>Page</th>
            <th>IP</th>
            <th>Location</th>
            <th>Browser / OS / Device</th>
            <th>Referrer</th>
          </tr>
        </thead>
        <tbody>
          <?php foreach ($results as $row): ?>
            <tr>
              <td class="small text-nowrap" data-visited-at="<?= e((new DateTime($row['visited_at']))->format(DateTime::ATOM)) ?>">
                <?= e(date('M j, g:ia', strtotime($row['visited_at']))) ?>
              </td>
              <td class="small" style="max-width:220px;word-break:break-all;"><?= e($row['page']) ?></td>
              <td class="small tnum text-nowrap"><?= e($row['ip']) ?></td>
              <td class="small text-nowrap">
                <?php
                  $location = array_filter([$row['city'], $row['region'], $row['country']]);
                  echo $location ? e(implode(', ', $location)) : '<span class="text-secondary">—</span>';
                ?>
              </td>
              <td class="small text-nowrap"><?= e(implode(' · ', array_filter([$row['browser'], $row['os'], $row['device']])) ?: '—') ?></td>
              <td class="small text-secondary" style="max-width:220px;word-break:break-all;"><?= e($row['referrer'] ?: '—') ?></td>
            </tr>
          <?php endforeach; ?>
        </tbody>
      </table>
    </div>
  <?php endif; ?>

  <?php if ($totalPages > 1): ?>
    <div class="d-flex justify-content-between mt-3">
      <a class="btn btn-outline-secondary btn-sm<?= $page <= 1 ? ' disabled' : '' ?>"
         href="?<?= e(log_filters_query_string($currentFilters, ['page' => $page - 1])) ?>">‹ Previous</a>
      <a class="btn btn-outline-secondary btn-sm<?= $page >= $totalPages ? ' disabled' : '' ?>"
         href="?<?= e(log_filters_query_string($currentFilters, ['page' => $page + 1])) ?>">Next ›</a>
    </div>
  <?php endif; ?>
</section>

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