using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using PlotLine.Services; namespace PlotLine.Controllers; [Authorize] public sealed class ProjectRestorePointsController( IProjectRestorePointService restorePoints, IProjectRestoreService projectRestore, ILogger logger) : Controller { public async Task Index(int projectId) { var model = await restorePoints.GetAsync(projectId); return model is null ? NotFound() : View(model); } [HttpPost] [ValidateAntiForgeryToken] public async Task Create(int projectId, string? restorePointName, string? notes) { try { if (await restorePoints.HasReachedManualLimitAsync(projectId)) { TempData["ProjectRestorePointMessage"] = ProjectRestorePointService.LimitReachedMessage; return RedirectToAction(nameof(Index), new { projectId }); } var created = await restorePoints.CreateManualAsync(projectId, restorePointName, notes); TempData["ProjectRestorePointMessage"] = created is null ? "Restore point could not be created because the project was not found." : "Restore point created."; } catch (Exception ex) { logger.LogError(ex, "Manual restore point creation failed for project {ProjectID}.", projectId); TempData["ProjectRestorePointMessage"] = "Restore point could not be created. Please try again, or check the application logs if the problem continues."; } return RedirectToAction(nameof(Index), new { projectId }); } public async Task Download(int projectId, int id) { try { var download = await restorePoints.DownloadAsync(id, projectId); if (download is null) { TempData["ProjectRestorePointMessage"] = "Restore point could not be found."; return RedirectToAction(nameof(Index), new { projectId }); } return File(System.Text.Encoding.UTF8.GetBytes(download.Json), download.ContentType, download.FileName); } catch (Exception ex) { logger.LogError(ex, "Restore point download failed for restore point {ProjectRestorePointID} in project {ProjectID}.", id, projectId); TempData["ProjectRestorePointMessage"] = "Restore point could not be downloaded. Please try again, or check the application logs if the problem continues."; return RedirectToAction(nameof(Index), new { projectId }); } } [HttpPost] [ValidateAntiForgeryToken] public async Task Restore(int projectId, int id) { try { var result = await projectRestore.RestoreAsync(projectId, id); TempData["ProjectRestorePointMessage"] = result.Message; } catch (Exception ex) { logger.LogError(ex, "Project restore failed unexpectedly for restore point {ProjectRestorePointID} in project {ProjectID}.", id, projectId); TempData["ProjectRestorePointMessage"] = "Restore failed. No project data was changed."; } return RedirectToAction(nameof(Index), new { projectId }); } [HttpPost] [ValidateAntiForgeryToken] public async Task Delete(int projectId, int id) { try { var deleted = await restorePoints.DeleteAsync(id, projectId); TempData["ProjectRestorePointMessage"] = deleted ? "Restore point deleted." : "Restore point could not be deleted. It may not exist."; } catch (Exception ex) { logger.LogError(ex, "Restore point delete failed unexpectedly for restore point {ProjectRestorePointID} in project {ProjectID}.", id, projectId); TempData["ProjectRestorePointMessage"] = "Restore point could not be deleted. Please try again, or check the application logs if the problem continues."; } return RedirectToAction(nameof(Index), new { projectId }); } }