<?php

declare(strict_types=1);

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 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->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->batchRunner->runNextBatch($execution->fresh(['package']) ?? $execution);
    }

    public function beginMigrationStage(HostSystemUpdateExecution $execution): void
    {
        $package = $this->contextResolver->resolveReadyPackage($execution);
        $manifest = $this->contextResolver->manifest($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 !== ''));
    }
}
