<?php
session_start();
include __DIR__ . '/auth.php';

include __DIR__ . '/includes/header.php';
include __DIR__ . '/includes/sidebar.php';
include $_SERVER['DOCUMENT_ROOT'] . '/includes/navigation.php';

/**
 * Cloudflare Web Stats (GraphQL)
 *
 * CHANGE MADE:
 * - Token + Zone ID are now loaded from:
 *   C:\inetpub\Authentication\api\oldiesandmore.php
 *
 * Nothing else changed.
 */

// ===============================
// ✅ LOAD SECRETS FROM SAFE FILE
// ===============================
$configPath = 'C:/inetpub/Authentication/api/oldiesandmore.php';

$CF_ZONE_ID   = '';
$CF_API_TOKEN = '';

if (file_exists($configPath)) {
    $cf = require $configPath;
    $CF_ZONE_ID   = trim((string)($cf['zone_id'] ?? ''));
    $CF_API_TOKEN = trim((string)($cf['api_token'] ?? ''));
}

// Fail fast if token is missing/dirty
$tokenMissing = ($CF_API_TOKEN === '' || preg_match('/\s/', $CF_API_TOKEN) || $CF_ZONE_ID === '');

// ----------------- Helpers -----------------
function iso_utc(int $ts): string {
    return gmdate('Y-m-d\TH:i:s\Z', $ts);
}

function fmt_int($n): string {
    if ($n === null || $n === '') return '—';
    return number_format((float)$n, 0, '.', ',');
}

function fmt_bytes($bytes): string {
    if ($bytes === null || $bytes === '') return '—';
    $bytes = (float)$bytes;
    $units = ['B','KB','MB','GB','TB'];
    $i = 0;
    while ($bytes >= 1024 && $i < count($units)-1) { $bytes /= 1024; $i++; }
    return number_format($bytes, $i === 0 ? 0 : 2) . ' ' . $units[$i];
}

function fmt_pct($n): string {
    if ($n === null || $n === '') return '—';
    return rtrim(rtrim(number_format((float)$n, 2, '.', ''), '0'), '.') . '%';
}

/**
 * REST GET helper (used for /user/tokens/verify in debug)
 */
function cf_rest_get(string $url, string $token): array {
    $token = trim((string)$token);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . $token,
            'Accept: application/json',
            'Content-Type: application/json',
        ],
    ]);

    $raw  = curl_exec($ch);
    $err  = curl_error($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($raw === false) {
        return ['success' => false, 'errors' => [['message' => 'cURL error: ' . $err]], '_http_code' => $code];
    }

    $json = json_decode($raw, true);
    if (!is_array($json)) {
        return ['success' => false, 'errors' => [['message' => 'Invalid JSON. HTTP ' . $code]], '_http_code' => $code, '_raw' => substr((string)$raw, 0, 300)];
    }

    $json['_http_code'] = $code;
    return $json;
}

/**
 * GraphQL POST helper
 */
function cf_gql(string $query, array $vars, string $token): array {
    $token = trim((string)$token);

    $ch = curl_init("https://api.cloudflare.com/client/v4/graphql");
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . $token,
            'Content-Type: application/json',
            'Accept: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode([
            'query' => $query,
            'variables' => $vars,
        ]),
    ]);

    $raw  = curl_exec($ch);
    $err  = curl_error($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($raw === false) {
        return ['_http_code' => $code, '_raw' => null, 'errors' => [['message' => 'cURL error: ' . $err]]];
    }

    $json = json_decode($raw, true);
    if (!is_array($json)) {
        return ['_http_code' => $code, '_raw' => substr((string)$raw, 0, 500), 'errors' => [['message' => 'Invalid JSON from GraphQL']]];
    }

    $json['_http_code'] = $code;
    return $json;
}

function extract_http_1h_groups(array $gql): array {
    $groups = $gql['data']['viewer']['zones'][0]['httpRequests1hGroups'] ?? [];
    $series = [];

    foreach ($groups as $row) {
        $series[] = [
            't' => $row['dimensions']['datetime'] ?? '',
            'requests' => $row['sum']['requests'] ?? null,
            'bytes' => $row['sum']['bytes'] ?? null,
            'cachedRequests' => $row['sum']['cachedRequests'] ?? null,
            'cachedBytes' => $row['sum']['cachedBytes'] ?? null,
            'threats' => $row['sum']['threats'] ?? null,
            'pageViews' => $row['sum']['pageViews'] ?? null,
            'uniques' => $row['uniq']['uniques'] ?? null,
        ];
    }

    return $series;
}

function totals_from_series(array $series): array {
    $tot = [
        'requests' => 0,
        'bytes' => 0,
        'cachedRequests' => 0,
        'cachedBytes' => 0,
        'threats' => 0,
        'pageViews' => 0,
        'uniques' => null, // best-effort: we’ll use max of buckets
        'cacheHitPct' => null,
    ];

    $maxUniques = null;

    foreach ($series as $r) {
        $tot['requests'] += (int)($r['requests'] ?? 0);
        $tot['bytes'] += (int)($r['bytes'] ?? 0);
        $tot['cachedRequests'] += (int)($r['cachedRequests'] ?? 0);
        $tot['cachedBytes'] += (int)($r['cachedBytes'] ?? 0);
        $tot['threats'] += (int)($r['threats'] ?? 0);
        $tot['pageViews'] += (int)($r['pageViews'] ?? 0);

        if ($r['uniques'] !== null) {
            $u = (int)$r['uniques'];
            $maxUniques = ($maxUniques === null) ? $u : max($maxUniques, $u);
        }
    }

    $tot['uniques'] = $maxUniques;
    $tot['cacheHitPct'] = ($tot['requests'] > 0) ? round(($tot['cachedRequests'] / $tot['requests']) * 100, 2) : null;

    return $tot;
}

// Tiny inline sparkline SVG (no JS)
function sparkline(array $values, int $w=220, int $h=40): string {
    $vals = array_values(array_filter($values, fn($v) => $v !== null && $v !== ''));
    if (count($vals) < 2) return '<span style="opacity:.7;">—</span>';

    $min = min($vals);
    $max = max($vals);
    $range = ($max - $min) ?: 1;

    $pts = [];
    $n = count($vals);
    for ($i=0; $i<$n; $i++) {
        $x = ($w - 4) * ($i / ($n - 1)) + 2;
        $y = ($h - 4) * (1 - (($vals[$i] - $min) / $range)) + 2;
        $pts[] = round($x,2) . ',' . round($y,2);
    }

    $poly = implode(' ', $pts);
    return '<svg width="'.$w.'" height="'.$h.'" viewBox="0 0 '.$w.' '.$h.'" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="trend">
        <polyline fill="none" stroke="currentColor" stroke-width="2" points="'.$poly.'"/>
    </svg>';
}

/* =========================================================
   FETCH STATS (Cloudflare limits apply)
   - 24h is safe
   - 72h is safe (3 days) and avoids the “too old / too wide” errors
   ========================================================= */
$now   = time();
$until = iso_utc($now);

$since24 = iso_utc($now - 86400);       // 24h
$since72 = iso_utc($now - 86400 * 3);   // 72h (3 days)

$GQL = <<<'GQL'
query($zoneTag: String!, $since: DateTime!, $until: DateTime!) {
  viewer {
    zones(filter: { zoneTag: $zoneTag }) {
      httpRequests1hGroups(
        limit: 1000
        filter: { datetime_geq: $since, datetime_leq: $until }
      ) {
        dimensions { datetime }
        sum {
          requests
          bytes
          cachedRequests
          cachedBytes
          threats
          pageViews
        }
        uniq { uniques }
      }
    }
  }
}
GQL;

$g24 = $g72 = $verify = null;
$s24 = $s72 = [];
$t24 = $t72 = [];
$errorMsg = null;

if (!$tokenMissing) {
    $vars24 = ['zoneTag' => $CF_ZONE_ID, 'since' => $since24, 'until' => $until];
    $vars72 = ['zoneTag' => $CF_ZONE_ID, 'since' => $since72, 'until' => $until];

    $g24 = cf_gql($GQL, $vars24, $CF_API_TOKEN);
    $g72 = cf_gql($GQL, $vars72, $CF_API_TOKEN);

    // REST verify (debug-only use, but cheap)
    $verify = cf_rest_get("https://api.cloudflare.com/client/v4/user/tokens/verify", $CF_API_TOKEN);

    if (!empty($g24['errors'])) {
        $errorMsg = $g24['errors'][0]['message'] ?? 'GraphQL error (24h).';
    } elseif (!empty($g72['errors'])) {
        $errorMsg = $g72['errors'][0]['message'] ?? 'GraphQL error (72h).';
    } else {
        $s24 = extract_http_1h_groups($g24);
        $s72 = extract_http_1h_groups($g72);

        $t24 = totals_from_series($s24);
        $t72 = totals_from_series($s72);
    }
}

/* ===========================
   DEBUG MODE
   Visit: westats.php?debug=1
   =========================== */
if (isset($_GET['debug']) && ($_SESSION['role'] ?? '') === 'admin') {
    header('Content-Type: text/plain; charset=utf-8');

    echo "=== SYSTEM ===\n";
    echo "curl loaded: " . (extension_loaded('curl') ? "YES\n" : "NO\n");
    echo "openssl loaded: " . (extension_loaded('openssl') ? "YES\n" : "NO\n");
    echo "token missing: " . ($tokenMissing ? "YES\n" : "NO\n");
    echo "token length: " . strlen($CF_API_TOKEN) . "\n";
    echo "contains whitespace: " . (preg_match('/\s/', $CF_API_TOKEN) ? "YES\n" : "NO\n");
    echo "zone id length: " . strlen($CF_ZONE_ID) . "\n";
    echo "token preview: " . ($CF_API_TOKEN ? (substr($CF_API_TOKEN, 0, 4) . "..." . substr($CF_API_TOKEN, -4)) : "—") . "\n";
    echo "config file exists: " . (file_exists($configPath) ? "YES\n" : "NO\n") . "\n";
    echo "config path: " . $configPath . "\n\n";

    echo "=== TOKEN VERIFY (REST) ===\n";
    echo "HTTP Code: " . ($verify['_http_code'] ?? 'none') . "\n";
    echo json_encode($verify, JSON_PRETTY_PRINT) . "\n\n";

    echo "=== GRAPHQL 24H ===\n";
    echo "HTTP Code: " . ($g24['_http_code'] ?? 'none') . "\n";
    echo "errors: " . json_encode($g24['errors'] ?? [], JSON_PRETTY_PRINT) . "\n";
    echo "first row: " . json_encode(($g24['data']['viewer']['zones'][0]['httpRequests1hGroups'][0] ?? null), JSON_PRETTY_PRINT) . "\n\n";

    echo "=== GRAPHQL 72H ===\n";
    echo "HTTP Code: " . ($g72['_http_code'] ?? 'none') . "\n";
    echo "errors: " . json_encode($g72['errors'] ?? [], JSON_PRETTY_PRINT) . "\n";
    echo "first row: " . json_encode(($g72['data']['viewer']['zones'][0]['httpRequests1hGroups'][0] ?? null), JSON_PRETTY_PRINT) . "\n\n";

    echo "=== TOTALS (24H) ===\n";
    echo json_encode($t24, JSON_PRETTY_PRINT) . "\n\n";
    echo "=== TOTALS (72H) ===\n";
    echo json_encode($t72, JSON_PRETTY_PRINT) . "\n";

    exit;
}
?>

<div class="main-wrap">
  <div class="content-panel">

    <!-- Title + subtle refresh -->
    <div style="display:flex;align-items:center;justify-content:space-between;gap:12px;">
      <h1 class="section-title center-text" style="margin:0;flex:1;">📈 Web Stats</h1>

      <?php
        // Keep current query string but remove/override "t" (cache buster)
        $qs = $_GET;
        unset($qs['t']);
        $baseUrl = strtok($_SERVER['REQUEST_URI'], '?');
        $refreshUrl = $baseUrl . (count($qs) ? ('?' . http_build_query($qs) . '&t=' . time()) : ('?t=' . time()));
      ?>
      <a href="<?php echo htmlspecialchars($refreshUrl); ?>"
         class="btn btn-accent"
         style="display:inline-flex;align-items:center;gap:8px;padding:.45em .75em;border-radius:999px;opacity:.9;text-decoration:none;">
        <span aria-hidden="true">↻</span>
        <span style="font-size:.95em;">Refresh</span>
      </a>
    </div>

    <div style="max-width:1100px;margin:0 auto;">

      <?php if ($tokenMissing): ?>
        <div class="clock-box" style="text-align:left;">
          <strong>Cloudflare API Token missing/invalid.</strong><br><br>
          Your admin page now loads secrets from:<br>
          <code><?php echo htmlspecialchars($configPath); ?></code><br><br>
          Make sure that file contains:<br>
          <code>zone_id</code> and <code>api_token</code> and has no spaces/newlines in the token.
        </div>

      <?php elseif ($errorMsg): ?>
        <div class="clock-box" style="text-align:left;">
          <strong>Could not load Cloudflare stats:</strong><br>
          <?php echo htmlspecialchars($errorMsg); ?><br><br>
          <small>Tip: try <code>?debug=1</code> (admin only) to see GraphQL + token verify output.</small>
        </div>

      <?php else: ?>

        <div class="admin-grid" style="grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));">

          <!-- 24H -->
          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">Last 24h Requests</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_int($t24['requests'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(fn($r)=>$r['requests'], $s24)); ?></div>
          </div>

          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">Last 24h Bandwidth</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_bytes($t24['bytes'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(fn($r)=>$r['bytes'], $s24)); ?></div>
          </div>

          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">Last 24h Uniques</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_int($t24['uniques'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(fn($r)=>$r['uniques'], $s24)); ?></div>
          </div>

          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">Last 24h Pageviews</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_int($t24['pageViews'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(fn($r)=>$r['pageViews'], $s24)); ?></div>
          </div>

          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">Last 24h Threats</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_int($t24['threats'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(fn($r)=>$r['threats'], $s24)); ?></div>
          </div>

          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">24h Cache Hit</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_pct($t24['cacheHitPct'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(function($r){
                $req = (int)($r['requests'] ?? 0);
                $c   = (int)($r['cachedRequests'] ?? 0);
                return $req > 0 ? round(($c/$req)*100, 2) : null;
            }, $s24)); ?></div>
          </div>

          <!-- 72H -->
          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">Last 72h Requests</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_int($t72['requests'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(fn($r)=>$r['requests'], $s72)); ?></div>
          </div>

          <div class="admin-card" style="text-decoration:none;">
            <div style="font-size:1.1em;font-weight:700;">Last 72h Bandwidth</div>
            <div style="font-size:1.6em;margin-top:.3em;"><?php echo fmt_bytes($t72['bytes'] ?? null); ?></div>
            <div style="margin-top:.5em;"><?php echo sparkline(array_map(fn($r)=>$r['bytes'], $s72)); ?></div>
          </div>

        </div>

      <?php endif; ?>

    </div>

  </div>
</div>

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