<?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\HostSystemUpdateExecutionStep;
use App\Models\HostSystemUpdateExecution;

/**
 * 执行 migrate（支持分批；同步编排可一次跑完全部批次）。
 */
final class HostSystemUpdateMigrationRunner
{
    public function __construct(
        private readonly HostSystemUpdateExecutionContextResolver $contextResolver,
        private readonly HostSystemUpdateMigrationBatchRunner $batchRunner,
        private readonly HostSystemUpdateMigrationBatchExecutor $batchExecutor,
        private readonly HostSystemUpdateMigrationStateStore $migrationStateStore,
        private readonly HostSystemUpdateExecutionLogger $executionLogger,
        private readonly SupportCenterAuditLogger $auditLogger,
    ) {}

    public function runMigrations(HostSystemUpdateExecution $execution): void
    {
        $package = $this->contextResolver->resolveReadyPackage($execution);
        $manifest = $this->contextResolver->manifest($execution);
        $declaredMigrations = $this->declaredMigrationPaths($manifest);
        $this->migrationStateStore->captureBaseline($execution);

        $this->auditLogger->logSystemUpdateMigrationStarted($execution, $package, count($declaredMigrations));
        $this->executionLogger->logStepStarted(
            $execution,
            HostSystemUpdateExecutionStep::RunMigrations->value,
            (string) __('dberp.system_update.post_apply.log.migration_started'),
            ['declared_migration_count' => count($declaredMigrations)],
        );

        while (true) {
            $result = $this->runNextMigrationBatch($execution);
            $execution = $execution->fresh(['package']) ?? $execution;

            if ($result->stageCompleted) {
                $this->batchRunner->logMigrationStageCompleted($execution, $result->progress);

                return;
            }
        }
    }

    public function runNextMigrationBatch(HostSystemUpdateExecution $execution): HostSystemUpdateMigrationBatchResult
    {
        return $this->batchExecutor->run($execution->fresh(['package']) ?? $execution);
    }

    public function beginMigrationStage(HostSystemUpdateExecution $execution): void
    {
        if ($this->migrationStateStore->hasBaseline($execution)) {
            return;
        }

        $package = $this->contextResolver->resolveReadyPackage($execution);
        $manifest = $this->contextResolver->manifest($execution);
        $this->migrationStateStore->captureBaseline($execution);

        $this->auditLogger->logSystemUpdateMigrationStarted(
            $execution,
            $package,
            count($this->declaredMigrationPaths($manifest)),
        );
        $this->executionLogger->logStepStarted(
            $execution,
            HostSystemUpdateExecutionStep::RunMigrations->value,
            (string) __('dberp.system_update.post_apply.log.migration_started'),
            ['declared_migration_count' => count($this->declaredMigrationPaths($manifest))],
        );
    }

    /**
     * @param  array<string, mixed>  $manifest
     * @return list<string>
     */
    private function declaredMigrationPaths(array $manifest): array
    {
        $migrations = $manifest[HostSystemUpdateManifestContract::MIGRATIONS] ?? [];

        if (! is_array($migrations)) {
            return [];
        }

        return array_values(array_filter($migrations, static fn (mixed $path): bool => is_string($path) && $path !== ''));
    }
}
