<?php

declare(strict_types=1);

namespace App\Services\SupportCenter;

use App\Enums\SupportCenter\HostSystemUpdateExecutionStatus;
use App\Models\HostSystemUpdateExecution;

/**
 * 浏览器分步更新失败/中断时的收尾：标记执行任务终态、清理会话、尽力退出维护模式。
 */
final class HostSystemUpdateBrowserFailureFinalizer
{
    public function __construct(
        private readonly HostSystemUpdateStepProgressStore $progressStore,
        private readonly HostSystemUpdateExecutionStateMachine $stateMachine,
        private readonly HostSystemUpdateMaintenanceModeService $maintenanceModeService,
    ) {}

    public function finalize(?string $sessionId, ?HostSystemUpdateExecution $execution = null): void
    {
        $execution = $execution?->fresh(['package', 'backups', 'logs'])
            ?? $this->resolveExecutionFromSession($sessionId)
            ?? $this->resolveLatestActiveExecution();

        if ($execution instanceof HostSystemUpdateExecution) {
            $this->markInterruptedIfStillActive($execution);
            $execution = $execution->fresh(['package', 'backups', 'logs']) ?? $execution;
            $this->maintenanceModeService->attemptLeaveMaintenanceOnFailure($execution);
        } else {
            $this->maintenanceModeService->attemptLeaveMaintenanceOnFailure(null);
        }

        $this->closeOpenStepSession($sessionId);
    }

    private function markInterruptedIfStillActive(HostSystemUpdateExecution $execution): void
    {
        $status = (string) ($execution->status ?? '');

        if (! in_array($status, HostSystemUpdateExecutionStatus::activeValues(), true)) {
            return;
        }

        $this->stateMachine->fail(
            $execution,
            'host_system_update_browser_interrupted',
            (string) __('dberp.system_update_center.errors.browser_update_interrupted'),
            ['source' => 'browser_failure_finalizer'],
        );
    }

    private function closeOpenStepSession(?string $sessionId): void
    {
        if ($sessionId === null || $sessionId === '') {
            return;
        }

        $progress = $this->progressStore->read($sessionId);

        if ($progress === null) {
            return;
        }

        if (! $progress->terminal) {
            $this->progressStore->markTerminal(
                $progress,
                failed: true,
                errorMessage: (string) __('dberp.system_update_center.errors.browser_update_interrupted'),
            );
        }

        $this->progressStore->delete($sessionId);
    }

    private function resolveExecutionFromSession(?string $sessionId): ?HostSystemUpdateExecution
    {
        if ($sessionId === null || $sessionId === '') {
            return null;
        }

        $progress = $this->progressStore->read($sessionId);
        $executionNo = $progress?->executionNo;

        if (! is_string($executionNo) || $executionNo === '') {
            return null;
        }

        return HostSystemUpdateExecution::query()
            ->where('execution_no', $executionNo)
            ->first();
    }

    private function resolveLatestActiveExecution(): ?HostSystemUpdateExecution
    {
        return HostSystemUpdateExecution::query()
            ->whereIn('status', HostSystemUpdateExecutionStatus::activeValues())
            ->latest('id')
            ->first();
    }
}
