<?php

declare(strict_types=1);

namespace App\Services\SupportCenter;

/**
 * 解析 manifest 中的 vendor 更新策略与文件清单。
 */
final class HostSystemUpdateVendorStrategyResolver
{
    public const STRATEGY_NONE = 'none';

    public const STRATEGY_INCLUDED_VENDOR = 'included_vendor';

    public const STRATEGY_COMPOSER_REQUIRED = 'composer_required';

    /**
     * @param  array<string, mixed>  $manifest
     */
    public function resolveStrategy(array $manifest): string
    {
        $vendor = $manifest[HostSystemUpdateManifestContract::VENDOR] ?? null;

        if (is_string($vendor)) {
            return $this->normalizeStrategy($vendor);
        }

        if (is_array($vendor) && is_string($vendor['strategy'] ?? null)) {
            return $this->normalizeStrategy($vendor['strategy']);
        }

        if (is_string($manifest['vendor_strategy'] ?? null)) {
            return $this->normalizeStrategy($manifest['vendor_strategy']);
        }

        return self::STRATEGY_NONE;
    }

    /**
     * @param  array<string, mixed>  $manifest
     * @return list<string>
     */
    public function resolveVendorFiles(array $manifest): array
    {
        $paths = [];

        $vendor = $manifest[HostSystemUpdateManifestContract::VENDOR] ?? null;

        if (is_array($vendor)) {
            $paths = array_merge($paths, $this->normalizePathList($vendor['files'] ?? null));
            $paths = array_merge($paths, $this->normalizePathList($vendor['vendor_path'] ?? null));
        }

        $paths = array_merge($paths, $this->normalizePathList($manifest['vendor_files'] ?? null));
        $paths = array_merge($paths, $this->normalizePathList($manifest['vendor_path'] ?? null));

        return array_values(array_unique($paths));
    }

    private function normalizeStrategy(string $strategy): string
    {
        $normalized = strtolower(trim($strategy));

        return match ($normalized) {
            self::STRATEGY_INCLUDED_VENDOR => self::STRATEGY_INCLUDED_VENDOR,
            self::STRATEGY_COMPOSER_REQUIRED => self::STRATEGY_COMPOSER_REQUIRED,
            default => self::STRATEGY_NONE,
        };
    }

    /**
     * @return list<string>
     */
    private function normalizePathList(mixed $value): array
    {
        if (is_string($value) && trim($value) !== '') {
            return [str_replace('\\', '/', trim($value))];
        }

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

        $paths = [];

        foreach ($value as $path) {
            if (is_string($path) && trim($path) !== '') {
                $paths[] = str_replace('\\', '/', trim($path));
            }
        }

        return $paths;
    }
}
