using NexusShell.Models;

namespace NexusShell.Services.Deployment;

/// <summary>
/// Full-package update flow — compares versions and replaces installed payload.
/// Delta/mandatory/dependency updates are stubbed in <see cref="NexusDeploymentModels"/>.
/// </summary>
public sealed class NexusPackageUpdater
{
    private readonly NexusPackageRepository _repository;
    private readonly NexusPackageInstaller _installer;
    private readonly NexusRollbackService _rollback;
    private readonly INexusPackageDeltaUpdater _deltaUpdater;

    public NexusPackageUpdater(
        NexusPackageRepository repository,
        NexusPackageInstaller installer,
        NexusRollbackService rollback,
        INexusPackageDeltaUpdater? deltaUpdater = null)
    {
        _repository = repository;
        _installer = installer;
        _rollback = rollback;
        _deltaUpdater = deltaUpdater ?? new NexusPackageDeltaUpdaterStub();
    }

    public bool IsUpdateAvailable(string packageId)
    {
        var manifest = _repository.GetById(packageId);
        var record = _repository.GetInstalledRecord(packageId);
        if (manifest is null || record is null || string.IsNullOrWhiteSpace(record.InstalledVersion))
        {
            return false;
        }

        return NexusPackageVersionComparer.IsLessThan(record.InstalledVersion, manifest.Version);
    }

    public async Task<NexusPackageManifest> ApplyFullUpdateAsync(
        string packageId,
        string packagePath,
        string? previousVersion,
        IProgress<string>? progress = null,
        CancellationToken cancellationToken = default)
    {
        if (!string.IsNullOrWhiteSpace(previousVersion))
        {
            progress?.Report("Gemmer rollback-snapshot…");
            _rollback.CreateSnapshot(packageId, previousVersion);
        }

        return await _installer.ExtractAsync(packagePath, packageId, progress, cancellationToken);
    }

    /// <summary>Stub — delta patches not available in POC.</summary>
    public Task<bool> TryApplyDeltaUpdateAsync(
        string packageId,
        string deltaPath,
        CancellationToken cancellationToken = default) =>
        _deltaUpdater.ApplyDeltaAsync(packageId, deltaPath, cancellationToken);
}
