using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using LiteDB; namespace AuthorBuddy.Web.Services; public class ProjectService : IProjectService { private readonly ILiteDatabase _db; private readonly IFileScannerService _fileScannerService; public ProjectService(ILiteDatabase db, IFileScannerService fileScannerService) { _db = db; _fileScannerService = fileScannerService; } public Task CreateNewProjectAsync(string projectName, string rootPath) { string[] subFolders = { "00_Drafts", "01_Fakten", "02_Characters", "03_Archive" }; foreach (var subFolder in subFolders) { Directory.CreateDirectory(Path.Combine(rootPath, subFolder)); } string readmePath = Path.Combine(rootPath, "00_Projekt_Info.md"); File.WriteAllText(readmePath, $"# Projekt: {projectName}\nErstellt am: {DateTime.Now}"); var col = _db.GetCollection("projects"); var entity = new ProjectEntity { Name = projectName, RootPath = rootPath, LastOpened = DateTime.Now }; col.Insert(entity); return Task.FromResult(entity.Id); } public Task> GetAllProjectsAsync() { var col = _db.GetCollection("projects"); var list = col.FindAll() .OrderByDescending(p => p.LastOpened) .Select(p => new Project { Id = p.Id, Name = p.Name, RootPath = p.RootPath }) .ToList(); return Task.FromResult(list); } public Task GetProjectAsync(int projectId) { var col = _db.GetCollection("projects"); var entity = col.FindById(projectId); if (entity == null) return Task.FromResult(null); return Task.FromResult(new Project { Id = entity.Id, Name = entity.Name, RootPath = entity.RootPath }); } public Task> GetProjectFileTreeAsync(int projectId) { var col = _db.GetCollection("projects"); var entity = col.FindById(projectId); if (entity == null || !Directory.Exists(entity.RootPath)) return Task.FromResult(new List()); var result = new List(); BuildTree(entity.RootPath, result, 0); return Task.FromResult(result); } private static void BuildTree(string directory, List items, int depth) { if (depth > 4) return; var dirInfo = new DirectoryInfo(directory); if (!dirInfo.Exists) return; foreach (var dir in dirInfo.GetDirectories().OrderBy(d => d.Name)) { var node = new FileTreeItem { Name = dir.Name, FullPath = dir.FullName, IsDirectory = true }; BuildTree(dir.FullName, node.Children, depth + 1); if (node.Children.Count > 0 || dir.Name.StartsWith("00_") || dir.Name.StartsWith("01_") || dir.Name.StartsWith("02_")) items.Add(node); } foreach (var file in dirInfo.GetFiles("*.md").OrderBy(f => f.Name)) { items.Add(new FileTreeItem { Name = file.Name, FullPath = file.FullName, IsDirectory = false }); } } public async Task SyncProjectFilesAsync(int projectId, string directoryPath, IProgress progress) { await _fileScannerService.ScanProjectFolderAsync(projectId, directoryPath, progress); } public Task CopyProjectAsync(int sourceProjectId, string newName, string newRootPath, int userId) { var col = _db.GetCollection("projects"); var source = col.FindById(sourceProjectId); if (source == null) throw new InvalidOperationException("Source project not found."); Directory.CreateDirectory(newRootPath); CopyDirectory(source.RootPath, newRootPath); var entity = new ProjectEntity { Name = newName, RootPath = newRootPath, LastOpened = DateTime.Now }; col.Insert(entity); var settings = _db.GetCollection("settings"); var projectSettings = settings.Find(s => s.UserId == userId && s.ProjectId == sourceProjectId); foreach (var s in projectSettings) { settings.Insert(new SettingEntity { Key = s.Key, Value = s.Value, UserId = userId, ProjectId = entity.Id }); } return Task.FromResult(entity.Id); } private static void CopyDirectory(string sourceDir, string destDir) { foreach (var dir in Directory.GetDirectories(sourceDir, "*", SearchOption.AllDirectories)) { Directory.CreateDirectory(dir.Replace(sourceDir, destDir)); } foreach (var file in Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories)) { var dest = file.Replace(sourceDir, destDir); File.Copy(file, dest, true); } } }