<?php
declare(strict_types=1);
namespace App\Services;

use RuntimeException;

final class UpdateVersionCompatibility
{
    public function normalize(string $version): string
    {
        $version=trim($version);
        if(!preg_match('/(?:^|[^0-9])(\d+\.\d+\.\d+(?:\.\d+)?)(?:[^0-9]|$)/',$version,$m)) {
            throw new RuntimeException('Numéro de version illisible : '.$version);
        }
        return $m[1];
    }

    /** @return array{ok:bool,installed:string,accepted:string,reason:string} */
    public function evaluate(string $installedVersion,array $manifest): array
    {
        $installed=$this->normalize($installedVersion);
        $sources=array_values(array_filter(array_map(fn($v)=>$this->normalize((string)$v),(array)($manifest['source_versions']??[]))));
        if($sources && in_array($installed,$sources,true)) {
            return ['ok'=>true,'installed'=>$installed,'accepted'=>'versions sources : '.implode(', ',$sources),'reason'=>'Version source explicitement acceptée.'];
        }
        $min=!empty($manifest['min_version'])?$this->normalize((string)$manifest['min_version']):'0.0.0';
        $max=!empty($manifest['max_version'])?$this->normalize((string)$manifest['max_version']):null;
        $branch=trim((string)($manifest['compatible_branch']??''));
        $rangeOk=version_compare($installed,$min,'>=')&&($max===null||version_compare($installed,$max,'<='));
        $branchOk=$branch===''||str_starts_with($installed,rtrim($branch,'.').'.');
        $accepted='minimum '.$min.($max?' · maximum '.$max:' · sans maximum').($branch!==''?' · branche '.$branch.'.x':'');
        return ['ok'=>$rangeOk&&$branchOk,'installed'=>$installed,'accepted'=>$accepted,'reason'=>$rangeOk&&$branchOk?'Plage compatible.':'Version hors de la plage déclarée.'];
    }
}
