<?php

declare(strict_types=1);

namespace app\common\service;

use support\Redis;
use Throwable;

/**
 * 热点缓存回源刷新队列：LPUSH / RPOP，由独立进程消费，削峰 Redis 与 DB 回读。
 * 业务线程在落库后仍会同步刷新缓存；队列任务为幂等补偿，避免瞬时高峰打满连接。
 */
final class GameHotDataWriteQueue
{
    public const OP_USER_REFRESH = 'user.refresh';

    public const OP_GC_REFRESH = 'gc.refresh';

    public const OP_GR_SYNC = 'gr.sync';

    public static function queueListKey(): string
    {
        $k = config('game_hot_cache.queue_list_key', 'dfw:q:hot_data_write');
        return is_string($k) && $k !== '' ? $k : 'dfw:q:hot_data_write';
    }

    public static function enabled(): bool
    {
        return filter_var(config('game_hot_cache.enable_cache_write_queue', true), FILTER_VALIDATE_BOOLEAN);
    }

    /**
     * @param array<string, mixed> $job 须含 op 字段
     */
    public static function enqueue(array $job): void
    {
        if (!self::enabled()) {
            return;
        }
        if (!isset($job['op']) || !is_string($job['op']) || $job['op'] === '') {
            return;
        }
        $job['v'] = 1;
        $job['ts'] = time();
        $max = self::maxQueueLength();
        try {
            if ($max > 0) {
                $len = Redis::lLen(self::queueListKey());
                if (is_int($len) && $len >= $max) {
                    Redis::rPop(self::queueListKey());
                }
            }
            Redis::lPush(self::queueListKey(), json_encode($job, JSON_UNESCAPED_UNICODE));
        } catch (Throwable) {
        }
    }

    public static function maxQueueLength(): int
    {
        $v = config('game_hot_cache.queue_max_length', 50000);
        $n = filter_var($v, FILTER_VALIDATE_INT);

        return ($n === false || $n < 0) ? 50000 : $n;
    }
}
