namespace NexusShell.Models;

/// <summary>
/// Update policy foundation — full-package updates implemented in Deployment Engine 1.0;
/// delta, mandatory enforcement, and dependency cascades remain stubs.
/// </summary>
public interface INexusPackageUpdateCoordinator
{
    /// <summary>True when catalog policy marks the gap as mandatory (stub: minNexusVersion set).</summary>
    bool IsMandatoryUpdate(NexusPackageManifest manifest, string? installedVersion);

    /// <summary>True when a rollback snapshot exists for the target version (stub — wired in Deployment 2.0).</summary>
    bool CanRollback(string packageId, string targetVersion);

    /// <summary>Ordered rollback candidates newest-first (stub).</summary>
    IReadOnlyList<string> GetRollbackCandidates(string packageId);

    /// <summary>Build an update plan including dependency gaps (plan only; execution via <see cref="Services.Deployment.NexusDeploymentService"/>).</summary>
    Task<NexusPackageUpdatePlan> PlanUpdateAsync(string packageId, CancellationToken cancellationToken = default);
}

public sealed class NexusPackageUpdatePlan
{
    public required string PackageId { get; init; }
    public required string FromVersion { get; init; }
    public required string ToVersion { get; init; }
    public bool IsMandatory { get; init; }
    public bool RequiresRestart { get; init; }
    public IReadOnlyList<string> DependencyPackageIds { get; init; } = [];
}

public sealed class NexusPackageUpdateCoordinatorStub : INexusPackageUpdateCoordinator
{
    public bool IsMandatoryUpdate(NexusPackageManifest manifest, string? installedVersion) =>
        !string.IsNullOrWhiteSpace(manifest.MinNexusVersion);

    public bool CanRollback(string packageId, string targetVersion) => false;

    public IReadOnlyList<string> GetRollbackCandidates(string packageId) => [];

    public Task<NexusPackageUpdatePlan> PlanUpdateAsync(string packageId, CancellationToken cancellationToken = default) =>
        Task.FromResult(new NexusPackageUpdatePlan
        {
            PackageId = packageId,
            FromVersion = "0.0.0",
            ToVersion = "0.0.0",
            IsMandatory = false,
            RequiresRestart = true,
        });
}

public interface INexusPackageDependencyResolver
{
    IReadOnlyList<string> ResolveInstallOrder(IEnumerable<string> packageIds);
    IReadOnlyList<string> GetMissingDependencies(NexusPackageManifest manifest, IReadOnlySet<string> installedIds);
}

public sealed class NexusPackageDependencyResolverStub : INexusPackageDependencyResolver
{
    public IReadOnlyList<string> ResolveInstallOrder(IEnumerable<string> packageIds) =>
        packageIds.Distinct(StringComparer.OrdinalIgnoreCase).ToList();

    public IReadOnlyList<string> GetMissingDependencies(NexusPackageManifest manifest, IReadOnlySet<string> installedIds) =>
        manifest.Dependencies
            .Where(d => !installedIds.Contains(d, StringComparer.OrdinalIgnoreCase))
            .ToList();
}
