<?php

/**
 * Performance monitoring utility for tracking API performance
 * Helps identify bottlenecks and optimize frequently used endpoints
 */
class PerformanceMonitor {
    private static $startTime;
    private static $memoryStart;
    private static $queryCount = 0;
    private static $cacheHits = 0;
    private static $cacheMisses = 0;
    private static $logFile = __DIR__ . '/../../logs/performance.log';
    
    /**
     * Start performance monitoring
     */
    public static function start() {
        self::$startTime = microtime(true);
        self::$memoryStart = memory_get_usage(true);
        self::$queryCount = 0;
        self::$cacheHits = 0;
        self::$cacheMisses = 0;
    }
    
    /**
     * End monitoring and log results
     */
    public static function end($endpoint = null, $additionalData = []) {
        if (!self::$startTime) {
            return;
        }
        
        $endTime = microtime(true);
        $memoryEnd = memory_get_usage(true);
        $peakMemory = memory_get_peak_usage(true);
        
        $metrics = [
            'timestamp' => date('Y-m-d H:i:s'),
            'endpoint' => $endpoint ?: $_SERVER['REQUEST_URI'] ?? 'unknown',
            'method' => $_SERVER['REQUEST_METHOD'] ?? 'unknown',
            'execution_time' => round(($endTime - self::$startTime) * 1000, 2), // ms
            'memory_used' => self::formatBytes($memoryEnd - self::$memoryStart),
            'peak_memory' => self::formatBytes($peakMemory),
            'query_count' => self::$queryCount,
            'cache_hits' => self::$cacheHits,
            'cache_misses' => self::$cacheMisses,
            'cache_hit_ratio' => self::$cacheHits + self::$cacheMisses > 0 
                ? round((self::$cacheHits / (self::$cacheHits + self::$cacheMisses)) * 100, 1) 
                : 0,
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
            'ip' => self::getClientIP(),
            'additional_data' => $additionalData
        ];
        
        // Log performance data
        self::logMetrics($metrics);
        
        // Add performance headers in development
        if (defined('ENVIRONMENT') && ENVIRONMENT === 'development') {
            header('X-Execution-Time: ' . $metrics['execution_time'] . 'ms');
            header('X-Memory-Used: ' . $metrics['memory_used']);
            header('X-Query-Count: ' . $metrics['query_count']);
            header('X-Cache-Hit-Ratio: ' . $metrics['cache_hit_ratio'] . '%');
        }
        
        return $metrics;
    }
    
    /**
     * Track database query
     */
    public static function trackQuery() {
        self::$queryCount++;
    }
    
    /**
     * Track cache hit
     */
    public static function trackCacheHit() {
        self::$cacheHits++;
    }
    
    /**
     * Track cache miss
     */
    public static function trackCacheMiss() {
        self::$cacheMisses++;
    }
    
    /**
     * Log performance metrics
     */
    private static function logMetrics($metrics) {
        // Only log slow requests or high memory usage
        if ($metrics['execution_time'] > 1000 || // > 1 second
            $metrics['query_count'] > 10 || // > 10 queries
            $metrics['cache_hit_ratio'] < 50) { // < 50% cache hit ratio
            
            $logEntry = json_encode($metrics) . "\n";
            file_put_contents(self::$logFile, $logEntry, FILE_APPEND | LOCK_EX);
        }
    }
    
    /**
     * Get performance summary for admin dashboard
     */
    public static function getSummary($hours = 24) {
        if (!file_exists(self::$logFile)) {
            return [
                'total_requests' => 0,
                'avg_execution_time' => 0,
                'slow_requests' => 0,
                'avg_cache_hit_ratio' => 0,
                'top_endpoints' => []
            ];
        }
        
        $lines = file(self::$logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        $cutoffTime = time() - ($hours * 3600);
        
        $requests = [];
        $totalTime = 0;
        $slowRequests = 0;
        $totalCacheRatio = 0;
        $endpointCounts = [];
        
        foreach ($lines as $line) {
            $data = json_decode($line, true);
            if (!$data || strtotime($data['timestamp']) < $cutoffTime) {
                continue;
            }
            
            $requests[] = $data;
            $totalTime += $data['execution_time'];
            
            if ($data['execution_time'] > 1000) {
                $slowRequests++;
            }
            
            $totalCacheRatio += $data['cache_hit_ratio'];
            
            $endpoint = $data['endpoint'];
            $endpointCounts[$endpoint] = ($endpointCounts[$endpoint] ?? 0) + 1;
        }
        
        $requestCount = count($requests);
        
        // Sort endpoints by frequency
        arsort($endpointCounts);
        $topEndpoints = array_slice($endpointCounts, 0, 10, true);
        
        return [
            'total_requests' => $requestCount,
            'avg_execution_time' => $requestCount > 0 ? round($totalTime / $requestCount, 2) : 0,
            'slow_requests' => $slowRequests,
            'slow_request_percentage' => $requestCount > 0 ? round(($slowRequests / $requestCount) * 100, 1) : 0,
            'avg_cache_hit_ratio' => $requestCount > 0 ? round($totalCacheRatio / $requestCount, 1) : 0,
            'top_endpoints' => $topEndpoints
        ];
    }
    
    /**
     * Clean old performance logs
     */
    public static function cleanup($days = 7) {
        if (!file_exists(self::$logFile)) {
            return 0;
        }
        
        $lines = file(self::$logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        $cutoffTime = time() - ($days * 24 * 3600);
        $keptLines = [];
        
        foreach ($lines as $line) {
            $data = json_decode($line, true);
            if ($data && strtotime($data['timestamp']) >= $cutoffTime) {
                $keptLines[] = $line;
            }
        }
        
        $removedCount = count($lines) - count($keptLines);
        
        if ($removedCount > 0) {
            file_put_contents(self::$logFile, implode("\n", $keptLines) . "\n");
        }
        
        return $removedCount;
    }
    
    /**
     * Format bytes to human readable format
     */
    private static function formatBytes($bytes, $precision = 2) {
        $units = ['B', 'KB', 'MB', 'GB'];
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, $precision) . ' ' . $units[$i];
    }
    
    /**
     * Get client IP address
     */
    private static function getClientIP() {
        $ipKeys = ['HTTP_CF_CONNECTING_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'];
        
        foreach ($ipKeys as $key) {
            if (!empty($_SERVER[$key])) {
                $ip = $_SERVER[$key];
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
        
        return $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    }
    
    /**
     * Middleware function to automatically track performance
     */
    public static function middleware($next) {
        self::start();
        
        // Execute the main logic
        $result = $next();
        
        // End monitoring
        self::end();
        
        return $result;
    }
}