<?php

declare(strict_types=1);

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

namespace App\Services\SupportCenter;

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

    public const STRATEGY_INCLUDED_VENDOR = 'included_vendor';

    public const STRATEGY_INCLUDED_VENDOR_BUNDLE = 'included_vendor_bundle';

    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_INCLUDED_VENDOR_BUNDLE => self::STRATEGY_INCLUDED_VENDOR_BUNDLE,
            self::STRATEGY_COMPOSER_REQUIRED => self::STRATEGY_COMPOSER_REQUIRED,
            default => self::STRATEGY_NONE,
        };
    }

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

        if (! is_array($vendor)) {
            return null;
        }

        $bundlePath = $vendor['bundle_path'] ?? null;

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

        return str_replace('\\', '/', trim($bundlePath));
    }

    public function requiresVendorDirectoryWrite(string $strategy): bool
    {
        return in_array($strategy, [
            self::STRATEGY_INCLUDED_VENDOR,
            self::STRATEGY_INCLUDED_VENDOR_BUNDLE,
            self::STRATEGY_COMPOSER_REQUIRED,
        ], true);
    }

    /**
     * @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;
    }
}
