<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Services\SupportCenter;

use Illuminate\Contracts\Cache\Lock;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;

/**
 * 自动更新检查的节流时间戳与并发锁（Cache，不阻塞页面渲染）。
 */
final class HostSystemUpdateAutoCheckStateStore
{
    public const CACHE_KEY_LAST_ATTEMPT = 'dberp.host_system_update.auto_check.last_attempt_at';

    public const CACHE_KEY_LAST_SUCCESS = 'dberp.host_system_update.auto_check.last_success_at';

    public const LOCK_NAME = 'dberp.host_system_update.auto_check.lock';

    public function lastAttemptAt(): ?Carbon
    {
        return $this->parseTimestamp(Cache::get(self::CACHE_KEY_LAST_ATTEMPT));
    }

    public function lastSuccessAt(): ?Carbon
    {
        return $this->parseTimestamp(Cache::get(self::CACHE_KEY_LAST_SUCCESS));
    }

    public function recordAttempt(): void
    {
        Cache::put(self::CACHE_KEY_LAST_ATTEMPT, now()->utc()->toIso8601String());
    }

    public function recordSuccess(): void
    {
        $now = now()->utc();
        Cache::put(self::CACHE_KEY_LAST_SUCCESS, $now->toIso8601String());
        Cache::put(self::CACHE_KEY_LAST_ATTEMPT, $now->toIso8601String());
    }

    public function isWithinIntervalHours(int $intervalHours): bool
    {
        $lastAttempt = $this->lastAttemptAt();

        if (! $lastAttempt instanceof Carbon) {
            return false;
        }

        return $lastAttempt->greaterThan(now()->utc()->subHours(max(1, $intervalHours)));
    }

    public function acquireLock(int $seconds): ?Lock
    {
        $lock = Cache::lock(self::LOCK_NAME, max(30, $seconds));

        return $lock->get() ? $lock : null;
    }

    private function parseTimestamp(mixed $value): ?Carbon
    {
        if (! is_string($value) || trim($value) === '') {
            return null;
        }

        try {
            return Carbon::parse($value)->utc();
        } catch (\Throwable) {
            return null;
        }
    }
}
