using System.Security.Cryptography; using TheCr3w.Shared.Models; namespace TheCr3w.Shared.External; public class FileDiffItem { public string Path { get; set; } = string.Empty; public string Action { get; set; } = "update"; // add, update, delete public long FileSizeBytes { get; set; } public string LocalSha256 { get; set; } = string.Empty; public string? RemoteSha256 { get; set; } } public class SyncPreviewResult { public int FilesToAdd { get; set; } public int FilesToUpdate { get; set; } public int FilesToDelete { get; set; } public long TotalTransferBytes { get; set; } public List DiffDetails { get; set; } = new(); } public interface IExternalDeploymentService { SyncPreviewResult ComputeSyncPreview(Dictionary localFiles, Dictionary remoteFiles); bool ValidateHostKey(string actualFingerprint, string? expectedFingerprint); } public class ExternalDeploymentService : IExternalDeploymentService { public SyncPreviewResult ComputeSyncPreview( Dictionary localFiles, Dictionary remoteFiles) { var result = new SyncPreviewResult(); foreach (var (path, (sha256, size)) in localFiles) { if (!remoteFiles.TryGetValue(path, out var remoteSha)) { result.FilesToAdd++; result.TotalTransferBytes += size; result.DiffDetails.Add(new FileDiffItem { Path = path, Action = "add", FileSizeBytes = size, LocalSha256 = sha256 }); } else if (!string.Equals(sha256, remoteSha, StringComparison.OrdinalIgnoreCase)) { result.FilesToUpdate++; result.TotalTransferBytes += size; result.DiffDetails.Add(new FileDiffItem { Path = path, Action = "update", FileSizeBytes = size, LocalSha256 = sha256, RemoteSha256 = remoteSha }); } } foreach (var (remotePath, remoteSha) in remoteFiles) { if (!localFiles.ContainsKey(remotePath)) { result.FilesToDelete++; result.DiffDetails.Add(new FileDiffItem { Path = remotePath, Action = "delete", RemoteSha256 = remoteSha }); } } return result; } public bool ValidateHostKey(string actualFingerprint, string? expectedFingerprint) { if (string.IsNullOrWhiteSpace(expectedFingerprint)) return false; // Rygorystyczny brak automatycznego akceptowania nieznanych kluczy return string.Equals(actualFingerprint.Trim(), expectedFingerprint.Trim(), StringComparison.OrdinalIgnoreCase); } }