<?php

declare(strict_types=1);

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;
        }
    }
}
