<?php
/**
 * ============================================================
 * ESCOBAR PERFORMANCE LOGGER
 * File  : perf_log.php
 * Cara  : include 'perf_log.php'; di awal config.php & process.php
 * Output: perf_log.txt — dicatat setiap request selesai
 * ============================================================
 */

// ── Rekam waktu start request (epoch + microsecond) ──────────
if (!defined('PERF_START')) {
    define('PERF_START', microtime(true));
}

// ── Storage checkpoint selama request ────────────────────────
$GLOBALS['_PERF'] = [
    'request_start' => PERF_START,
    'checkpoints'   => [],
    'log_file'      => __DIR__ . '/perf_log.txt',
    'max_log_size'  => 2 * 1024 * 1024, // 2 MB, lalu auto-rotate
];

/**
 * perf_checkpoint($label)
 * Panggil sebelum & sesudah operasi yang dicurigai lambat.
 *
 * Contoh:
 *   perf_checkpoint('SEBELUM_ADB_connect');
 *   controlTV($ip, 'connect');
 *   perf_checkpoint('SETELAH_ADB_connect');
 */
function perf_checkpoint(string $label): void {
    $elapsed_ms = round((microtime(true) - PERF_START) * 1000, 2);
    $GLOBALS['_PERF']['checkpoints'][] = [
        'label'      => $label,
        'elapsed_ms' => $elapsed_ms,
    ];
}

/**
 * perf_time_func(callable $fn, string $label): mixed
 * Wrap fungsi/closure, catat berapa ms fungsi itu jalan.
 *
 * Contoh:
 *   $result = perf_time_func(fn() => controlTV($ip, 'start_overlay', $args), 'ADB_start_overlay');
 */
function perf_time_func(callable $fn, string $label) {
    perf_checkpoint("START_$label");
    $result = $fn();
    perf_checkpoint("END_$label");
    return $result;
}

/**
 * perf_flush()
 * Tulis ringkasan ke perf_log.txt.
 * Dipanggil otomatis via register_shutdown_function().
 */
function perf_flush(): void {
    $cfg   = $GLOBALS['_PERF'] ?? null;
    if (!$cfg) return;

    $total_ms  = round((microtime(true) - $cfg['request_start']) * 1000, 2);
    $date      = date('Y-m-d H:i:s');
    $uri       = $_SERVER['REQUEST_URI']  ?? '-';
    $method    = $_SERVER['REQUEST_METHOD'] ?? '-';
    $action    = $_REQUEST['action'] ?? '-';
    $tv_id     = $_REQUEST['tv_id']  ?? '-';

    // ── Hitung delta antar checkpoint ──
    $cp_lines  = '';
    $prev_ms   = 0;
    foreach ($cfg['checkpoints'] as $cp) {
        $delta     = round($cp['elapsed_ms'] - $prev_ms, 2);
        $flag      = ($delta >= 1000) ? ' ⚠️  LAMBAT' : (($delta >= 300) ? ' ⚡ SLOW' : '');
        $cp_lines .= sprintf(
            "    [%8.2f ms] (+%7.2f ms)  %s%s\n",
            $cp['elapsed_ms'], $delta, $cp['label'], $flag
        );
        $prev_ms = $cp['elapsed_ms'];
    }

    // ── Tentukan severity total ──
    if ($total_ms >= 5000)      $severity = '🔴 CRITICAL';
    elseif ($total_ms >= 2000)  $severity = '🟠 SLOW    ';
    elseif ($total_ms >= 500)   $severity = '🟡 WARN    ';
    else                        $severity = '🟢 OK      ';

    $log = <<<LOG
════════════════════════════════════════════════════════════════
[$date] $severity  Total: {$total_ms} ms
  Method  : $method  |  Action: $action  |  TV: $tv_id
  URI     : $uri
  Memory  : {$GLOBALS['_PERF_MEM_START']} KB → %s KB (peak: %s KB)
  Checkpoints:
$cp_lines
LOG;

    $log = sprintf(
        $log,
        round(memory_get_usage() / 1024, 1),
        round(memory_get_peak_usage() / 1024, 1)
    );

    // ── Auto-rotate jika file terlalu besar ──
    $log_file = $cfg['log_file'];
    if (file_exists($log_file) && filesize($log_file) > $cfg['max_log_size']) {
        rename($log_file, $log_file . '.' . date('Ymd_His') . '.bak');
    }

    file_put_contents($log_file, $log, FILE_APPEND | LOCK_EX);
}

// Simpan memory awal
$GLOBALS['_PERF_MEM_START'] = round(memory_get_usage() / 1024, 1);

// Daftarkan flush otomatis saat request selesai
register_shutdown_function('perf_flush');