using Microsoft.EntityFrameworkCore; using public_valetax.Data; using public_valetax.Models; using public_valetax.DTOs; using public_valetax.Exceptions; namespace public_valetax.Repositories { public class TreeRepository(ApplicationDbContext _context) : ITreeRepository { public async Task GetTreeByNameAsync(string name) { return await _context.Trees .Include(t => t.Nodes) .FirstOrDefaultAsync(t => t.Name == name); } public async Task CreateTreeAsync(string name) { var tree = new Tree { Name = name, CreatedAt = DateTime.UtcNow }; if (await _context.Trees.AnyAsync(t => t.Name == name)) { throw new SecureException("Tree with such name already exist"); } _context.Trees.Add(tree); await _context.SaveChangesAsync(); return tree; } public async Task GetNodeByIdAsync(long nodeId) { return await _context.Nodes.FindAsync(nodeId); } public async Task CreateNodeAsync(long treeId, long? parentId, string name) { // Verify that parent node belongs to the same tree if provided if (parentId.HasValue) { var parentNode = await _context.Nodes.FindAsync(parentId.Value); if (parentNode == null || parentNode.TreeId != treeId) { throw new SecureException("Parent node does not belong to the specified tree"); } } // Check if a node with the same name already exists in the same tree var existingNode = await _context.Nodes .FirstOrDefaultAsync(n => n.TreeId == treeId && n.Name == name && n.ParentId == parentId); if (existingNode != null) { throw new SecureException("A node with the same name already exists in this location"); } var node = new Node { TreeId = treeId, ParentId = parentId, Name = name, CreatedAt = DateTime.UtcNow }; _context.Nodes.Add(node); await _context.SaveChangesAsync(); return node; } public async Task DeleteNodeAsync(long nodeId) { var node = await _context.Nodes .Include(n => n.Children) .FirstOrDefaultAsync(n => n.Id == nodeId); if (node == null) { throw new SecureException("Node not found"); } // Check if node has children if (node.Children.Any()) { throw new SecureException("You have to delete all children nodes first"); } _context.Nodes.Remove(node); await _context.SaveChangesAsync(); } public async Task RenameNodeAsync(long nodeId, string newName) { var node = await _context.Nodes.FindAsync(nodeId); if (node == null) { throw new SecureException("Node not found"); } // Check if another node with the same name already exists in the same parent var existingNode = await _context.Nodes .FirstOrDefaultAsync(n => n.TreeId == node.TreeId && n.Name == newName && n.ParentId == node.ParentId && n.Id != nodeId); if (existingNode != null) { throw new SecureException("A node with the same name already exists in this location"); } node.Name = newName; await _context.SaveChangesAsync(); } public async Task GetTreeStructureAsync(string treeName) { var tree = await _context.Trees .Include(t => t.Nodes) .FirstOrDefaultAsync(t => t.Name == treeName); if (tree == null) { return null; } // Build the tree structure recursively var rootNodes = tree.Nodes .Where(n => n.ParentId == null) .Select(n => BuildMNode(n, tree.Nodes)) .ToList(); // If no root node exists, create one if (!rootNodes.Any()) { return new MNode { Id = 0, Name = tree.Name, Children = [] }; } return rootNodes.First(); } private MNode BuildMNode(Node node, ICollection allNodes) { var mNode = new MNode { Id = node.Id, Name = node.Name, Children = [] }; // Add children recursively var children = allNodes.Where(n => n.ParentId == node.Id).ToList(); foreach (var child in children) { mNode.Children.Add(BuildMNode(child, allNodes)); } return mNode; } } }