PlotDirector/PlotLine/Services/ProjectRestorePointService.cs
2026-06-05 16:15:49 +01:00

98 lines
3.4 KiB
C#

using PlotLine.Data;
using PlotLine.Models;
using PlotLine.ViewModels;
namespace PlotLine.Services;
public interface IProjectRestorePointService
{
Task<ProjectRestorePointListViewModel?> GetAsync(int projectId);
Task<ProjectRestorePoint?> CreateManualAsync(int projectId, string? restorePointName, string? notes);
Task<ProjectRestorePointDownload?> DownloadAsync(int projectRestorePointId, int projectId);
}
public sealed class ProjectRestorePointService(
IProjectRepository projects,
IProjectExportService projectExports,
IProjectRestorePointRepository restorePoints,
ILogger<ProjectRestorePointService> logger) : IProjectRestorePointService
{
private const string ManualRestorePointType = "Manual";
public async Task<ProjectRestorePointListViewModel?> GetAsync(int projectId)
{
var project = await projects.GetAsync(projectId);
if (project is null)
{
return null;
}
return new ProjectRestorePointListViewModel
{
Project = project,
RestorePoints = await restorePoints.ListAsync(projectId)
};
}
public async Task<ProjectRestorePoint?> CreateManualAsync(int projectId, string? restorePointName, string? notes)
{
var export = await projectExports.ExportAsync(projectId);
if (export is null)
{
logger.LogWarning("Manual restore point requested for missing project {ProjectID}.", projectId);
return null;
}
var name = string.IsNullOrWhiteSpace(restorePointName)
? $"Manual restore point - {DateTime.Now:yyyy-MM-dd HH:mm}"
: restorePointName.Trim();
var created = await restorePoints.CreateAsync(projectId, name, ManualRestorePointType, export.Json, Clean(notes));
logger.LogInformation("Manual restore point {ProjectRestorePointID} created for project {ProjectID} with {JsonSizeBytes} JSON bytes.",
created.ProjectRestorePointID,
projectId,
created.JsonSizeBytes);
return created;
}
public async Task<ProjectRestorePointDownload?> DownloadAsync(int projectRestorePointId, int projectId)
{
var restorePoint = await restorePoints.GetAsync(projectRestorePointId, projectId);
if (restorePoint?.JsonData is null)
{
logger.LogWarning("Restore point download requested for missing restore point {ProjectRestorePointID} in project {ProjectID}.", projectRestorePointId, projectId);
return null;
}
return new ProjectRestorePointDownload
{
FileName = BuildFileName(restorePoint.ProjectName, restorePoint.CreatedDateUtc),
ContentType = "application/json",
Json = restorePoint.JsonData
};
}
private static string? Clean(string? value)
{
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}
private static string BuildFileName(string projectName, DateTime createdDateUtc)
{
var safeTitle = new string(projectName
.Select(c => Path.GetInvalidFileNameChars().Contains(c) ? '_' : c)
.ToArray())
.Trim();
safeTitle = string.Join("_", safeTitle.Split(' ', StringSplitOptions.RemoveEmptyEntries));
if (string.IsNullOrWhiteSpace(safeTitle))
{
safeTitle = "PlotWeaver_Project";
}
return $"{safeTitle}_RestorePoint_{createdDateUtc:yyyy-MM-dd_HHmm}.plotweaver";
}
}