using NexusShell.Models;

namespace NexusShell.Services;

public sealed class NexusPackageValidator
{
    private static readonly HashSet<string> RequiredFields =
    [
        nameof(NexusPackageManifest.Id),
        nameof(NexusPackageManifest.Name),
        nameof(NexusPackageManifest.Version),
        nameof(NexusPackageManifest.Publisher),
        nameof(NexusPackageManifest.EntryPoint),
        nameof(NexusPackageManifest.Category),
    ];

    public NexusPackageValidationResult Validate(NexusPackageManifest? manifest)
    {
        if (manifest is null)
        {
            return NexusPackageValidationResult.Failure("Manifest is null.");
        }

        var errors = new List<string>();

        if (string.IsNullOrWhiteSpace(manifest.Id))
        {
            errors.Add("id is required.");
        }

        if (string.IsNullOrWhiteSpace(manifest.Name))
        {
            errors.Add("name is required.");
        }

        if (string.IsNullOrWhiteSpace(manifest.Version))
        {
            errors.Add("version is required.");
        }
        else if (!NexusPackageVersionComparer.IsValidSemVer(manifest.Version))
        {
            errors.Add($"version '{manifest.Version}' is not valid semver.");
        }

        if (string.IsNullOrWhiteSpace(manifest.Publisher))
        {
            errors.Add("publisher is required.");
        }

        if (string.IsNullOrWhiteSpace(manifest.EntryPoint))
        {
            errors.Add("entryPoint is required.");
        }

        if (string.IsNullOrWhiteSpace(manifest.Category))
        {
            errors.Add("category is required.");
        }

        if (!string.IsNullOrWhiteSpace(manifest.MinNexusVersion) &&
            !NexusPackageVersionComparer.IsValidSemVer(manifest.MinNexusVersion))
        {
            errors.Add($"minNexusVersion '{manifest.MinNexusVersion}' is not valid semver.");
        }

        foreach (var dependency in manifest.Dependencies)
        {
            if (string.IsNullOrWhiteSpace(dependency))
            {
                errors.Add("dependencies must not contain empty values.");
            }
        }

        return errors.Count == 0
            ? NexusPackageValidationResult.Success(manifest)
            : NexusPackageValidationResult.Failure(errors.ToArray());
    }

    public IReadOnlyList<string> GetRequiredFieldNames() => RequiredFields.ToList();
}
