<?php
/**
 * Site Traffic — free-tier per-site analytics page.
 *
 * Reads pre-aggregated daily snapshots written by the whp-traffic-aggregator
 * cron into /docker/users/<user>/whp-analytics/<YYYY-MM>.sqlite3 via the
 * shared TrafficAnalytics library.
 *
 * Without ?site_id=N, renders a picker of sites the user can view. With
 * ?site_id=N, shows that site's snapshot. ?month=YYYY-MM is optional.
 */

if (!defined('AUTH_USER')) {
    header('Location: login.php');
    exit;
}

require_once('/docker/whp/web/libs/mysqlmgmt.php');
require_once('/docker/whp/web/libs/traffic_analytics.php');

$is_root = (AUTH_USER === 'root');
$site_id = isset($_GET['site_id']) ? (int)$_GET['site_id'] : 0;

$db = null;
try {
    $db = (new mysqlmgmt())->getMySQLConnection();
    if (!$db) {
        throw new Exception('Database connection failed');
    }
} catch (Throwable $e) {
    error_log('site-traffic db: ' . $e->getMessage());
    echo '<div class="alert alert-danger"><i class="fa fa-exclamation-triangle me-2"></i>Unable to load traffic data: database unavailable.</div>';
    return;
}

// No site selected: render a picker of sites the caller can view, then bail.
// Using `return` (not `exit`) so index.php's surrounding chrome and footer
// still render around the picker.
if ($site_id <= 0) {
    if ($is_root) {
        $sites = $db->query("
            SELECT s.id, s.site_name, s.username,
                   COALESCE(sd.fqdn, d.domain_name) AS primary_domain
            FROM whp.sites s
            JOIN whp.domains d ON s.primary_domain_id = d.id
            LEFT JOIN whp.site_domains sd ON sd.site_id = s.id AND sd.is_primary = 1
            ORDER BY s.username ASC, s.site_name ASC
        ")->fetchAll(PDO::FETCH_ASSOC);
    } else {
        $stmt = $db->prepare("
            SELECT s.id, s.site_name, s.username,
                   COALESCE(sd.fqdn, d.domain_name) AS primary_domain
            FROM whp.sites s
            JOIN whp.domains d ON s.primary_domain_id = d.id
            LEFT JOIN whp.site_domains sd ON sd.site_id = s.id AND sd.is_primary = 1
            WHERE s.username = ?
            ORDER BY s.site_name ASC
        ");
        $stmt->execute([AUTH_USER]);
        $sites = $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    $hp = function ($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); };
    ?>
    <?php if (empty($sites)): ?>
        <div class="alert alert-info"><i class="fa fa-info-circle me-2"></i>No sites available to display traffic for.</div>
    <?php else: ?>
        <div class="card shadow-sm">
            <div class="card-header d-flex justify-content-between align-items-center">
                <span><i class="fa fa-list-ul me-2"></i>Select a site</span>
                <span class="badge bg-secondary"><?= count($sites) ?> site<?= count($sites) === 1 ? '' : 's' ?></span>
            </div>
            <div class="card-body p-0">
                <table class="table table-hover mb-0 align-middle">
                    <thead class="table-light">
                        <tr>
                            <th><i class="fa fa-server me-1"></i>Site</th>
                            <th><i class="fa fa-globe me-1"></i>Primary Domain</th>
                            <?php if ($is_root): ?><th><i class="fa fa-user me-1"></i>Owner</th><?php endif; ?>
                            <th class="text-end">&nbsp;</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php foreach ($sites as $s): ?>
                        <tr>
                            <td><?= $hp($s['site_name']) ?></td>
                            <td><strong><?= $hp($s['primary_domain'] ?? '') ?></strong></td>
                            <?php if ($is_root): ?><td><?= $hp($s['username']) ?></td><?php endif; ?>
                            <td class="text-end">
                                <a class="btn btn-sm btn-info" href="index.php?page=site-traffic&amp;site_id=<?= (int)$s['id'] ?>">
                                    <i class="fa fa-line-chart me-1"></i>View Traffic
                                </a>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        </div>
    <?php endif; ?>
    <?php
    return;
}

// Per-site lookup. Mirrors the COALESCE join used by ai-monitor-customer.php
// and api/sites.php so wildcard FQDNs from site_domains take precedence.
$site = null;
try {
    $stmt = $db->prepare("
        SELECT s.id, s.site_name, s.username,
               COALESCE(sd.fqdn, d.domain_name) AS primary_domain
        FROM whp.sites s
        JOIN whp.domains d ON s.primary_domain_id = d.id
        LEFT JOIN whp.site_domains sd ON s.id = sd.site_id AND sd.is_primary = 1
        WHERE s.id = ?
    ");
    $stmt->execute([$site_id]);
    $site = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
    error_log('site-traffic: ' . $e->getMessage());
}

if (!$site) {
    $_SESSION['permission_error'] = 'Site not found.';
    header('Location: index.php?page=site-traffic');
    exit;
}

if (!$is_root && $site['username'] !== AUTH_USER) {
    $_SESSION['permission_error'] = 'You do not have permission to view this site.';
    header('Location: index.php?page=site-traffic');
    exit;
}

$username = $site['username'];
$site_name = $site['site_name'];
$primary_domain = $site['primary_domain'] ?? '';

// Month selection — defaults to current; the picker only offers months that
// actually have a SQLite file.
$month = isset($_GET['month']) ? (string)$_GET['month'] : date('Y-m');
if (!preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', $month)) {
    $month = date('Y-m');
}

$today_str = date('Y-m-d');
$yesterday_str = date('Y-m-d', strtotime('-1 day'));

$ta = new TrafficAnalytics();

$today = null;
$yesterday = null;
$top_urls = [];
$top_bandwidth = [];
$month_summary = [];
$available_months = [];
$data_error = null;

try {
    $today = $ta->getDailyTotals($username, $site_id, $today_str);
    $yesterday = $ta->getDailyTotals($username, $site_id, $yesterday_str);
    $top_urls = $ta->getTopUrls($username, $site_id, $yesterday_str);
    $top_bandwidth = $ta->getTopBandwidth($username, $site_id, $yesterday_str);
    $month_summary = $ta->getMonthSummary($username, $site_id, $month);
    $available_months = $ta->listAvailableMonths($username);
} catch (Throwable $e) {
    error_log('site-traffic data load: ' . $e->getMessage());
    $data_error = 'Unable to load analytics data.';
}

// Today's data is only present after the overnight cron run; until then we
// surface yesterday's numbers with a clear "Yesterday" label so the snapshot
// row is never empty just because we caught the user mid-day.
$snapshot_label = 'Today';
$snapshot = $today;
if (!$snapshot && $yesterday) {
    $snapshot_label = 'Yesterday';
    $snapshot = $yesterday;
}

if (!function_exists('whp_format_bytes')) {
    function whp_format_bytes(int $bytes, int $precision = 2): string {
        if ($bytes <= 0) return '0 B';
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $i = 0;
        $b = (float)$bytes;
        while ($b >= 1024 && $i < count($units) - 1) {
            $b /= 1024;
            $i++;
        }
        return round($b, $precision) . ' ' . $units[$i];
    }
}

$h = function ($v): string {
    return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8');
};
?>

<!-- Site context bar (the page chrome already shows the "Site Traffic" h1
     and breadcrumb; this strip identifies WHICH site is being viewed and
     gives a clear way back to the picker). -->
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
    <div class="d-flex align-items-center gap-2">
        <span class="badge bg-primary fs-6"><i class="fa fa-server me-1"></i><?= $h($site_name) ?></span>
        <span><i class="fa fa-globe me-1"></i><strong><?= $h($primary_domain) ?></strong></span>
    </div>
    <a class="btn btn-sm btn-outline-secondary" href="index.php?page=site-traffic">
        <i class="fa fa-arrow-left me-1"></i>All sites
    </a>
</div>

<?php if ($data_error): ?>
<div class="alert alert-danger"><i class="fa fa-exclamation-triangle me-2"></i><?= $h($data_error) ?></div>
<?php endif; ?>

<!-- Snapshot card (today, or yesterday as fallback) -->
<div class="card mb-4">
    <div class="card-header d-flex justify-content-between align-items-center">
        <h5 class="card-title mb-0"><i class="fa fa-line-chart me-2"></i><?= $h($snapshot_label) ?>'s Snapshot</h5>
        <?php if ($snapshot): ?>
        <span class="badge bg-secondary"><?= $h($snapshot['date']) ?></span>
        <?php endif; ?>
    </div>
    <div class="card-body">
        <div class="row g-3 text-center">
            <div class="col-md-4">
                <div class="text-muted text-uppercase small mb-1">Total Requests</div>
                <div class="display-6 fw-bold">
                    <?= $snapshot ? number_format((int)$snapshot['total_requests']) : '&mdash;' ?>
                </div>
            </div>
            <div class="col-md-4">
                <div class="text-muted text-uppercase small mb-1">
                    Estimated Human Page Views
                    <i class="fa fa-info-circle ms-1"
                       data-bs-toggle="tooltip"
                       data-bs-placement="top"
                       title="Excludes assets (images, JS, CSS, fonts), known bots, and error responses (4xx/5xx)."
                       style="cursor: help;"></i>
                </div>
                <div class="display-6 fw-bold">
                    <?= $snapshot ? number_format((int)$snapshot['human_views']) : '&mdash;' ?>
                </div>
            </div>
            <div class="col-md-4">
                <div class="text-muted text-uppercase small mb-1">Bandwidth Served</div>
                <div class="display-6 fw-bold">
                    <?= $snapshot ? $h(whp_format_bytes((int)$snapshot['bytes_sent'])) : '&mdash;' ?>
                </div>
            </div>
        </div>
        <?php if (!$snapshot): ?>
        <div class="text-center text-muted small mt-3">
            <i class="fa fa-clock-o me-1"></i>
            No data yet. The overnight scan runs at 1 AM and processes the prior day's logs.
        </div>
        <?php elseif ($snapshot_label === 'Yesterday'): ?>
        <div class="text-center text-muted small mt-3">
            Today's data updates after midnight.
        </div>
        <?php endif; ?>
    </div>
</div>

<!-- Top URLs and Top Bandwidth (yesterday) -->
<div class="row g-4 mb-4">
    <div class="col-lg-6">
        <div class="card h-100">
            <div class="card-header">
                <h5 class="card-title mb-0"><i class="fa fa-list-ol me-2"></i>Top 10 URLs <small class="text-muted">(yesterday)</small></h5>
            </div>
            <div class="card-body p-0">
                <?php if (empty($top_urls)): ?>
                <div class="p-4 text-center text-muted">
                    No data yet &mdash; check back after the next overnight scan.
                </div>
                <?php else: ?>
                <div class="table-responsive">
                    <table class="table table-bordered table-hover mb-0">
                        <thead>
                            <tr>
                                <th style="width: 60px;">#</th>
                                <th>Path</th>
                                <th style="width: 120px;" class="text-end">Hits</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($top_urls as $row): ?>
                            <tr>
                                <td><?= (int)$row['rank'] ?></td>
                                <td class="text-break"><code><?= $h($row['url']) ?></code></td>
                                <td class="text-end"><?= number_format((int)$row['hits']) ?></td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
                <?php endif; ?>
            </div>
        </div>
    </div>
    <div class="col-lg-6">
        <div class="card h-100">
            <div class="card-header">
                <h5 class="card-title mb-0"><i class="fa fa-cloud-download me-2"></i>Top 10 Bandwidth Consumers <small class="text-muted">(yesterday)</small></h5>
            </div>
            <div class="card-body p-0">
                <?php if (empty($top_bandwidth)): ?>
                <div class="p-4 text-center text-muted">
                    No data yet &mdash; check back after the next overnight scan.
                </div>
                <?php else: ?>
                <div class="table-responsive">
                    <table class="table table-bordered table-hover mb-0">
                        <thead>
                            <tr>
                                <th style="width: 60px;">#</th>
                                <th>Path</th>
                                <th style="width: 110px;" class="text-end">Bytes</th>
                                <th style="width: 90px;" class="text-end">Hits</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($top_bandwidth as $row): ?>
                            <tr>
                                <td><?= (int)$row['rank'] ?></td>
                                <td class="text-break"><code><?= $h($row['url']) ?></code></td>
                                <td class="text-end"><?= $h(whp_format_bytes((int)$row['bytes_total'])) ?></td>
                                <td class="text-end"><?= number_format((int)$row['hits']) ?></td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
                <?php endif; ?>
            </div>
        </div>
    </div>
</div>

<!-- Month-to-date table + month picker -->
<div class="card mb-4">
    <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
        <h5 class="card-title mb-0"><i class="fa fa-calendar me-2"></i>Daily Totals</h5>
        <form method="get" class="d-flex align-items-center gap-2 mb-0">
            <input type="hidden" name="page" value="site-traffic">
            <input type="hidden" name="site_id" value="<?= (int)$site_id ?>">
            <label for="monthSelect" class="form-label mb-0 text-muted small">Month:</label>
            <select id="monthSelect" name="month" class="form-select form-select-sm" style="width: auto;" onchange="this.form.submit()">
                <?php
                // Always include the currently selected month so the picker reflects
                // the URL even if no data exists yet for that month.
                $month_options = $available_months;
                if (!in_array($month, $month_options, true)) {
                    array_unshift($month_options, $month);
                }
                foreach ($month_options as $ym):
                    $label = date('F Y', strtotime($ym . '-01'));
                ?>
                <option value="<?= $h($ym) ?>"<?= $ym === $month ? ' selected' : '' ?>><?= $h($label) ?></option>
                <?php endforeach; ?>
            </select>
            <noscript><button type="submit" class="btn btn-sm btn-primary">Go</button></noscript>
        </form>
    </div>
    <div class="card-body p-0">
        <?php if (empty($month_summary)): ?>
        <div class="p-4 text-center text-muted">
            No data for <?= $h(date('F Y', strtotime($month . '-01'))) ?> yet.
        </div>
        <?php else: ?>
        <div class="table-responsive">
            <table class="table table-bordered table-hover mb-0">
                <thead>
                    <tr>
                        <th>Date</th>
                        <th class="text-end">Requests</th>
                        <th class="text-end">Human Views</th>
                        <th class="text-end">Bandwidth</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($month_summary as $row): ?>
                    <tr>
                        <td><?= $h($row['date']) ?></td>
                        <td class="text-end"><?= number_format((int)$row['total_requests']) ?></td>
                        <td class="text-end"><?= number_format((int)$row['human_views']) ?></td>
                        <td class="text-end"><?= $h(whp_format_bytes((int)$row['bytes_sent'])) ?></td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
        <?php endif; ?>
    </div>
</div>

<script>
// Activate Bootstrap tooltips on the snapshot card.
document.addEventListener('DOMContentLoaded', function () {
    var triggers = document.querySelectorAll('[data-bs-toggle="tooltip"]');
    triggers.forEach(function (el) {
        if (window.bootstrap && bootstrap.Tooltip) {
            new bootstrap.Tooltip(el);
        }
    });
});
</script>
