<?php
/** JSON-lines runtime logger with recursion and writing locks. */
if (!function_exists('wr_runtime_log_dir')) { function wr_runtime_log_dir(){ return dirname(__DIR__).DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.'runtime'; } }
if (!function_exists('wr_runtime_log_file')) { function wr_runtime_log_file(){ return wr_runtime_log_dir().DIRECTORY_SEPARATOR.'winracing_runtime_v50_3.jsonl'; } }
if (!function_exists('wr_runtime_sanitize')) {
    function wr_runtime_sanitize($value, $depth=0){
        if($depth>5) return '[depth-limit]';
        if(is_array($value)){ $out=array(); foreach($value as $k=>$v){ $lk=strtolower((string)$k); $out[$k]=(preg_match('/pass(word)?|pwd|secret|token|authorization|cookie|dsn/i',$lk))?'[REDACTED]':wr_runtime_sanitize($v,$depth+1); } return $out; }
        if(is_object($value)) return '[object '.get_class($value).']';
        if(is_string($value)){
            $value=preg_replace('/(password|passwd|pwd|secret|token)\\s*[:=]\\s*[^\\s,;]+/i','$1=[REDACTED]',$value);
            $value=preg_replace("/(mysqli\\([^)]*\\)|mysql:\\/\\/[^\\s]+)/i",'[DB-CONNECTION-REDACTED]',$value);
            return strlen($value)>8000?substr($value,0,8000).'...[truncated]':$value;
        }
        return $value;
    }
}
if (!function_exists('wr_runtime_log')) {
    function wr_runtime_log($level,$message,$context=array(),$file=null,$line=null){
        static $recursion=false, $writing=false;
        if($recursion || $writing) return false;
        $recursion=true;
        try{
            $dir=wr_runtime_log_dir();
            if(!is_dir($dir) && !@mkdir($dir,0775,true) && !is_dir($dir)){ $recursion=false; return false; }
            $record=array(
                'timestamp'=>function_exists('wr_timezone_fallback_timestamp')?wr_timezone_fallback_timestamp():sprintf('unix:%.6f',microtime(true)),
                'level'=>strtoupper((string)$level), 'request_id'=>defined('WR_RUNTIME_REQUEST_ID')?WR_RUNTIME_REQUEST_ID:'unknown',
                'message'=>(string)$message, 'execution_ms'=>function_exists('wr_runtime_execution_ms')?wr_runtime_execution_ms():0,
                'memory_mb'=>function_exists('wr_runtime_memory_mb')?wr_runtime_memory_mb():round(memory_get_usage(true)/1048576,3),
                'source_file'=>$file, 'source_line'=>$line, 'context'=>wr_runtime_sanitize($context)
            );
            $json=json_encode($record,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_PARTIAL_OUTPUT_ON_ERROR);
            if($json===false){ $json='{"level":"ERROR","message":"logger-json-encode-failed"}'; }
            $writing=true; $fp=@fopen(wr_runtime_log_file(),'ab');
            if(!$fp){ $writing=false; $recursion=false; return false; }
            if(@flock($fp,LOCK_EX)){ @fwrite($fp,$json.PHP_EOL); @fflush($fp); @flock($fp,LOCK_UN); }
            @fclose($fp); $writing=false; $recursion=false; return true;
        }catch(Throwable $e){ $writing=false; $recursion=false; return false; }
    }
}
