<?php
/**
 * 判定流水线各阶段耗时统计
 */
class CloakPipelineTimer
{
    /** @var float */
    private static $startedAt = 0.0;

    /** @var array<int, array{name:string,ms:float}> */
    private static $stages = [];

    /** @var string */
    private static $currentStage = '';

    /** @var float */
    private static $stageStartedAt = 0.0;

    public static function init()
    {
        self::$startedAt      = microtime(true);
        self::$stages         = [];
        self::$currentStage   = '';
        self::$stageStartedAt = 0.0;
    }

    public static function stage($name)
    {
        self::endCurrentStage();
        self::$currentStage   = (string) $name;
        self::$stageStartedAt = microtime(true);
    }

    public static function finish()
    {
        self::endCurrentStage();
        $totalMs = round((microtime(true) - self::$startedAt) * 1000, 2);
        $payload = [
            'total_ms' => $totalMs,
            'stages'   => self::$stages,
        ];
        $json = json_encode($payload, JSON_UNESCAPED_UNICODE);
        $GLOBALS['__cloak_judge_timing']      = $json;
        $GLOBALS['__cloak_judge_timing_text'] = self::formatText($payload);
        return $payload;
    }

    /**
     * @return string
     */
    public static function summaryText()
    {
        if (!empty($GLOBALS['__cloak_judge_timing_text'])) {
            return (string) $GLOBALS['__cloak_judge_timing_text'];
        }
        if (!empty($GLOBALS['__cloak_judge_timing'])) {
            $decoded = json_decode((string) $GLOBALS['__cloak_judge_timing'], true);
            if (is_array($decoded)) {
                return self::formatText($decoded);
            }
        }
        return '';
    }

    /**
     * @param array $payload
     */
    public static function formatText(array $payload)
    {
        $parts = [];
        if (isset($payload['total_ms'])) {
            $parts[] = '总计 ' . $payload['total_ms'] . 'ms';
        }
        if (!empty($payload['stages']) && is_array($payload['stages'])) {
            foreach ($payload['stages'] as $stage) {
                if (!is_array($stage)) {
                    continue;
                }
                $name = $stage['name'] ?? '';
                $ms   = $stage['ms'] ?? 0;
                if ($name !== '') {
                    $parts[] = $name . ' ' . $ms . 'ms';
                }
            }
        }
        return implode(' | ', $parts);
    }

    private static function endCurrentStage()
    {
        if (self::$currentStage === '' || self::$stageStartedAt <= 0) {
            return;
        }
        self::$stages[] = [
            'name' => self::$currentStage,
            'ms'   => round((microtime(true) - self::$stageStartedAt) * 1000, 2),
        ];
        self::$currentStage   = '';
        self::$stageStartedAt = 0.0;
    }
}
