<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use App\Enums\SupportCenter\HostSystemUpdateExecutionStatus;
use App\Models\HostSystemUpdateExecution;
use App\Services\SupportCenter\HostSystemUpdateStepProgressStore;
use App\Support\DberpLivewireRequest;
use App\Support\DberpMaintenanceDownExceptPaths;
use Closure;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
use Illuminate\Http\Request;
use Throwable;

/**
 * 维护模式下：存在进行中的系统更新执行任务时，放行 Livewire 分步请求与更新中心页（Laravel 已启动后第二层判断；早退见 down except）。
 */
final class AllowLivewireUpdateDuringSystemUpdateMaintenance extends PreventRequestsDuringMaintenance
{
    public function handle($request, Closure $next)
    {
        if ($this->shouldBypassForActiveSystemUpdate($request)) {
            return $next($request);
        }

        return parent::handle($request, $next);
    }

    private function shouldBypassForActiveSystemUpdate(Request $request): bool
    {
        if (! $this->hasActiveSystemUpdateExecution() && ! $this->hasNonTerminalWebStepSession()) {
            return false;
        }

        return DberpLivewireRequest::isComponentUpdateRequest($request)
            || DberpLivewireRequest::isFrontendAssetRequest($request)
            || app(DberpMaintenanceDownExceptPaths::class)->isSystemUpdateCenterRequest($request);
    }

    private function hasNonTerminalWebStepSession(): bool
    {
        try {
            return app(HostSystemUpdateStepProgressStore::class)->hasNonTerminalSession();
        } catch (Throwable) {
            return false;
        }
    }

    private function hasActiveSystemUpdateExecution(): bool
    {
        try {
            return HostSystemUpdateExecution::query()
                ->whereIn('status', HostSystemUpdateExecutionStatus::activeValues())
                ->exists();
        } catch (Throwable) {
            return false;
        }
    }
}
