package de.oaa.xxx.location; import de.oaa.xxx.location.entity.LocationAdminEntity; import de.oaa.xxx.location.repository.LocationAdminRepository; import de.oaa.xxx.location.repository.LocationRepository; import de.oaa.xxx.user.UserRepository; import de.oaa.xxx.user.UserService; import jakarta.transaction.Transactional; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.security.Principal; import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.UUID; @RestController @RequestMapping("/locations/{locationId}/admins") public class LocationAdminController { record AdminDto(UUID userId, String name, String profilePicture, boolean isOwner) {} record AddAdminRequest(UUID userId) {} record TransferOwnerRequest(UUID userId) {} private final LocationRepository locationRepo; private final LocationAdminRepository adminRepo; private final UserRepository userRepo; private final UserService userService; public LocationAdminController(LocationRepository locationRepo, LocationAdminRepository adminRepo, UserRepository userRepo, UserService userService) { this.locationRepo = locationRepo; this.adminRepo = adminRepo; this.userRepo = userRepo; this.userService = userService; } // ── Hilfsmethoden ──────────────────────────────────────────────────────── private boolean isAdmin(UUID locationId, UUID userId, de.oaa.xxx.location.entity.LocationEntity loc) { return loc.getOwnerId().equals(userId) || adminRepo.existsByLocationIdAndUserId(locationId, userId); } private AdminDto toDto(UUID userId, de.oaa.xxx.location.entity.LocationEntity loc) { return userRepo.findById(userId).map(u -> new AdminDto( u.getUserId(), u.getName(), u.getProfilePicture(), u.getUserId().equals(loc.getOwnerId()))) .orElse(null); } // ── Admins auflisten ───────────────────────────────────────────────────── @GetMapping public ResponseEntity> list( @PathVariable UUID locationId, Principal principal) { userService.requireUser(principal); var locOpt = locationRepo.findById(locationId); if (locOpt.isEmpty()) return ResponseEntity.notFound().build(); var loc = locOpt.get(); // Inhaber ist immer erster Eintrag List admins = new java.util.ArrayList<>(); userRepo.findById(loc.getOwnerId()).ifPresent(owner -> admins.add(new AdminDto(owner.getUserId(), owner.getName(), owner.getProfilePicture(), true))); adminRepo.findByLocationId(locationId).stream() .filter(a -> !a.getUserId().equals(loc.getOwnerId())) // Inhaber nicht doppelt .map(a -> toDto(a.getUserId(), loc)) .filter(java.util.Objects::nonNull) .forEach(admins::add); return ResponseEntity.ok(admins); } // ── Admin hinzufügen ────────────────────────────────────────────────────── @PostMapping public ResponseEntity add( @PathVariable UUID locationId, @RequestBody AddAdminRequest req, Principal principal) { UUID myId = userService.requireUser(principal).getUserId(); var locOpt = locationRepo.findById(locationId); if (locOpt.isEmpty()) return ResponseEntity.notFound().build(); var loc = locOpt.get(); if (!isAdmin(locationId, myId, loc)) return ResponseEntity.status(403).build(); if (req.userId() == null || !userRepo.existsById(req.userId())) return ResponseEntity.badRequest().build(); // Inhaber muss nicht eingetragen werden if (req.userId().equals(loc.getOwnerId())) return ResponseEntity.badRequest().build(); // Bereits Admin? if (adminRepo.existsByLocationIdAndUserId(locationId, req.userId())) return ResponseEntity.status(409).build(); LocationAdminEntity entity = new LocationAdminEntity(); entity.setAdminId(UUID.randomUUID()); entity.setLocationId(locationId); entity.setUserId(req.userId()); entity.setAddedAt(LocalDateTime.now()); adminRepo.save(entity); return ResponseEntity.status(201).body(toDto(req.userId(), loc)); } // ── Admin entfernen ─────────────────────────────────────────────────────── @Transactional @DeleteMapping("/{userId}") public ResponseEntity remove( @PathVariable UUID locationId, @PathVariable UUID userId, Principal principal) { UUID myId = userService.requireUser(principal).getUserId(); var locOpt = locationRepo.findById(locationId); if (locOpt.isEmpty()) return ResponseEntity.notFound().build(); var loc = locOpt.get(); if (!isAdmin(locationId, myId, loc)) return ResponseEntity.status(403).build(); // Inhaber darf nicht entfernt werden if (userId.equals(loc.getOwnerId())) return ResponseEntity.status(403).build(); adminRepo.deleteByLocationIdAndUserId(locationId, userId); return ResponseEntity.noContent().build(); } // ── Inhaberwechsel ──────────────────────────────────────────────────────── @Transactional @PutMapping("/transfer-owner") public ResponseEntity> transferOwner( @PathVariable UUID locationId, @RequestBody TransferOwnerRequest req, Principal principal) { UUID myId = userService.requireUser(principal).getUserId(); var locOpt = locationRepo.findById(locationId); if (locOpt.isEmpty()) return ResponseEntity.notFound().build(); var loc = locOpt.get(); // Nur der aktuelle Inhaber darf übertragen if (!loc.getOwnerId().equals(myId)) return ResponseEntity.status(403).build(); if (req.userId() == null || !userRepo.existsById(req.userId())) return ResponseEntity.badRequest().build(); if (req.userId().equals(myId)) return ResponseEntity.badRequest().build(); // Neuer Inhaber als Admin eintragen (falls noch nicht), alter Inhaber wird normaler Admin if (!adminRepo.existsByLocationIdAndUserId(locationId, myId)) { LocationAdminEntity a = new LocationAdminEntity(); a.setAdminId(UUID.randomUUID()); a.setLocationId(locationId); a.setUserId(myId); a.setAddedAt(LocalDateTime.now()); adminRepo.save(a); } // Neuen Inhaber aus Admin-Liste entfernen (er ist jetzt Owner) adminRepo.deleteByLocationIdAndUserId(locationId, req.userId()); loc.setOwnerId(req.userId()); locationRepo.save(loc); return ResponseEntity.ok(Map.of("newOwnerId", req.userId())); } }