<?php

declare(strict_types=1);

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

namespace App\Services\SupportCenter;

use App\Enums\SupportCenter\HostSystemUpdateStepPhase;

/**
 * 分步更新会话进度（持久化于 storage，跨 HTTP 请求续跑）。
 */
final readonly class HostSystemUpdateStepProgress
{
    public function __construct(
        public string $sessionId,
        public HostSystemUpdateStepPhase $phase,
        public ?string $executionNo,
        public bool $terminal,
        public bool $failed,
        public ?string $errorMessage,
        public ?HostSystemUpdateMigrationProgress $migrationProgress,
        public bool $migratePhaseComplete,
        public ?HostSystemUpdateBatchProgress $batchProgress,
        public string $startedAt,
        public string $updatedAt,
    ) {}

    public static function initial(string $sessionId, string $timestamp): self
    {
        return new self(
            sessionId: $sessionId,
            phase: HostSystemUpdateStepPhase::BootstrapCheck,
            executionNo: null,
            terminal: false,
            failed: false,
            errorMessage: null,
            migrationProgress: null,
            migratePhaseComplete: false,
            batchProgress: null,
            startedAt: $timestamp,
            updatedAt: $timestamp,
        );
    }

    /**
     * @param  array<string, mixed>  $payload
     */
    public static function fromArray(array $payload): self
    {
        $migration = $payload['migration_progress'] ?? null;
        $batch = $payload['batch_progress'] ?? null;
        $phaseValue = (string) ($payload['phase'] ?? HostSystemUpdateStepPhase::BootstrapCheck->value);

        return new self(
            sessionId: (string) ($payload['session_id'] ?? ''),
            phase: HostSystemUpdateStepPhase::tryFrom($phaseValue) ?? HostSystemUpdateStepPhase::BootstrapCheck,
            executionNo: isset($payload['execution_no']) && is_string($payload['execution_no']) && $payload['execution_no'] !== ''
                ? $payload['execution_no']
                : null,
            terminal: (bool) ($payload['terminal'] ?? false),
            failed: (bool) ($payload['failed'] ?? false),
            errorMessage: isset($payload['error_message']) && is_string($payload['error_message'])
                ? $payload['error_message']
                : null,
            migrationProgress: is_array($migration)
                ? HostSystemUpdateMigrationProgress::fromArray($migration)
                : null,
            migratePhaseComplete: (bool) ($payload['migrate_phase_complete'] ?? false),
            batchProgress: is_array($batch)
                ? HostSystemUpdateBatchProgress::fromArray($batch)
                : null,
            startedAt: (string) ($payload['started_at'] ?? now()->toIso8601String()),
            updatedAt: (string) ($payload['updated_at'] ?? now()->toIso8601String()),
        );
    }

    /**
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'session_id' => $this->sessionId,
            'phase' => $this->phase->value,
            'execution_no' => $this->executionNo,
            'terminal' => $this->terminal,
            'failed' => $this->failed,
            'error_message' => $this->errorMessage,
            'migration_progress' => $this->migrationProgress?->toArray(),
            'migrate_phase_complete' => $this->migratePhaseComplete,
            'batch_progress' => $this->batchProgress?->toArray(),
            'started_at' => $this->startedAt,
            'updated_at' => $this->updatedAt,
        ];
    }
}
