<?php
/**
 * WinRacing Audit Fix Knife 1 — Runtime Logger v50.1
 * Additive only. Does not change score or decision logic.
 */
class ChairmanRuntimeLoggerV501 {
    private static $startedAt = 0.0;
    private static $runId = '';
    private static $logFile = '';
    private static $installed = false;

    public static function install($context='runtime') {
        if (self::$installed) return;
        self::$installed = true;
        self::$startedAt = microtime(true);
        self::$runId = date('Ymd_His') . '_' . substr(md5(uniqid('', true)), 0, 8);

        $dir = dirname(__DIR__, 2) . '/logs/chairman';
        if (!is_dir($dir)) @mkdir($dir, 0775, true);
        self::$logFile = $dir . '/chairman_' . date('Y-m-d') . '.log';

        set_error_handler(function($severity, $message, $file, $line) use ($context) {
            $suppressed = (error_reporting() === 0);
            ChairmanRuntimeLoggerV501::log('PHP_ERROR', array(
                'context'=>$context,
                'severity'=>$severity,
                'message'=>$message,
                'file'=>$file,
                'line'=>$line,
                'suppressed'=>$suppressed
            ));
            return false; // keep original PHP behaviour
        });

        set_exception_handler(function($e) use ($context) {
            ChairmanRuntimeLoggerV501::log('UNCAUGHT_EXCEPTION', array(
                'context'=>$context,
                'type'=>get_class($e),
                'message'=>$e->getMessage(),
                'file'=>$e->getFile(),
                'line'=>$e->getLine(),
                'trace'=>$e->getTraceAsString()
            ));
            if (!headers_sent()) http_response_code(500);
            echo 'WinRacing runtime error. Run ID: ' . htmlspecialchars(ChairmanRuntimeLoggerV501::runId(), ENT_QUOTES, 'UTF-8');
        });

        register_shutdown_function(function() use ($context) {
            $last = error_get_last();
            if ($last && in_array($last['type'], array(E_ERROR,E_PARSE,E_CORE_ERROR,E_COMPILE_ERROR,E_USER_ERROR), true)) {
                ChairmanRuntimeLoggerV501::log('FATAL_SHUTDOWN', array(
                    'context'=>$context,
                    'message'=>$last['message'],
                    'file'=>$last['file'],
                    'line'=>$last['line']
                ));
            }
        });

        self::log('REQUEST_START', array(
            'context'=>$context,
            'method'=>isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:'',
            'uri'=>isset($_SERVER['REQUEST_URI'])?$_SERVER['REQUEST_URI']:'',
            'php'=>PHP_VERSION
        ));
    }

    public static function log($type, array $data=array()) {
        $entry = array(
            'time'=>date('c'),
            'run_id'=>self::$runId,
            'type'=>$type,
            'data'=>$data
        );
        if (self::$logFile !== '') {
            @file_put_contents(self::$logFile, json_encode($entry, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) . PHP_EOL, FILE_APPEND|LOCK_EX);
        }
    }

    public static function runId() { return self::$runId; }
    public static function executionMs() {
        return self::$startedAt > 0 ? round((microtime(true)-self::$startedAt)*1000, 2) : 0;
    }
    public static function logFile() { return self::$logFile; }
}
