package samuelb.capripol.Controllers;

//import jdk.management.resource.internal.inst.InitInstrumentation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import samuelb.capripol.*;
import samuelb.capripol.Repositories.*;
import samuelb.capripol.Services.GroupService;
import samuelb.capripol.Services.RoleService;
import samuelb.capripol.Services.UserDetailsServiceImpl;

import java.awt.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.security.Principal;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/*
Controller for the Admin panel. Most of these methods function in the same way
in the sense that "...Data()" methods provide each tables modal with the needed data.
DataTable populated with AdminData()
Edit/Creating each entity type is also done similar to each other; checks which fields
have been passed from the modal - if present, set them and save entities.
 */
@Controller
public class AdminController {

    @Autowired
    private GroupRepository groupRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private FocusRepository focusRepository;

    @Autowired
    private FrameworkRepository frameworkRepository;

    @Autowired
    private GroupService groupService;

    @Autowired
    private SightingRepository sightingRepository;

    private static Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private RatingRepository ratingRepository;

    @Autowired
    private RoleService roleService;

    @Autowired
    private GroupRoleRepository groupRoleRepository;

    @Autowired
    private GroupUserRoleRepository groupUserRoleRepository;


    private BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();

    @GetMapping("/Admin")
    public ModelAndView admin(Model model){
        return new ModelAndView("Admin");
    }

    //Loads data according to what table has been selected to load, returns JSON for datatables
    //Each user/group/framework as iterated over and their respective details are added to data which is the object datatables will use
    @GetMapping(value = "/AdminData", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<String[]> adminData(@RequestParam (required = false) String clicked, Model model, Principal principal) {
        List<String[]> data = new ArrayList<>();
        //clicked will be null if its initial page load
        if (clicked == null || clicked.equals("user")) {
            List<User> users = userRepository.findAll();
            for(User user: users){
                String[] userDetails = {user.getUsername(), user.getEmail(), user.allRolesToString(), user.groupsToString()};
                data.add(userDetails);
            }
            model.addAttribute("users", users);
        } else if (clicked.equals("group")) {
            List<Group> groups = groupRepository.findAll();
            for(Group group: groups){
                Framework framework = group.getFramework();
                if(framework == null){
                    String[] groupDetails = {group.getGroupName(), group.groupMembersToString(), "None", "None"};
                    data.add(groupDetails);
                }else{
                    String[] groupDetails = {group.getGroupName(), group.groupMembersToString(), group.getFramework().getFrameworkName(), group.getFramework().fociToString()};
                    data.add(groupDetails);
                }
            }
        } else if(clicked.equals("framework")){
            List<Framework> frameworks = frameworkRepository.findAll();
            for(Framework framework: frameworks){
                String[] frameworkDetails = {framework.getFrameworkName(), framework.fociToString(), framework.groupsToString()};
                data.add(frameworkDetails);
            }
        }else{
            List<Focus> foci = focusRepository.findAll();
            for(Focus focus: foci){
                String[] fociDetails = {focus.getFocusName(), focus.getFocusCategory(), focus.getFocusExplanation()};
                data.add(fociDetails);
            }
        }
        return data;
    }

    //Provides data for the Admin  based on whether the user is editing or creating a user
    @GetMapping(value="/UserData")
    public ModelAndView userData(@RequestParam (required = false) String username, @RequestParam String buttonType, Model model){
        List<Group> groups = new LinkedList<>();
        Set<Role> roles = new HashSet<>();
        if(buttonType.equals("edit")){//if user clicked edit
            User user = userRepository.findByUserName(username);
            if(user != null){
                model.addAttribute("user", user);
                model.addAttribute("foci", focusRepository.findAll());
                model.addAttribute("edit", "edit");
                model.addAttribute("formAction", "/AdminEditUser"); //setting the modals form accordingly
                groups = groupRepository.findByUserID(user.getUserId());
                List<Group> allGroups = groupRepository.findAll();
                allGroups.removeAll(groups); //removing users current groups to ensure those available are groups the user is not already apart of
                roles = user.getSystemRoles();
                List<Role> allRoles = roleRepository.findAll();
                allRoles.removeAll(roles);
                model.addAttribute("groups", groups);
                model.addAttribute("allGroups", allGroups);
                model.addAttribute("roles", roles);
                model.addAttribute("allRoles", allRoles);
                return new ModelAndView("AdminModal");
            }else {
                model.addAttribute("error", "Error, User: "+username+" no longer exists.");
                return new ModelAndView("Admin");
            }
        }else{
            //creating a user
            model.addAttribute("user", "user");
            model.addAttribute("roles", roleRepository.findAll());
            model.addAttribute("create", "create");
            groups = groupRepository.findAll();
            model.addAttribute("groups", groups);
            model.addAttribute("foci", focusRepository.findAll());
            model.addAttribute("formAction", "/AdminCreateUser");
            return new ModelAndView("AdminModal");
        }

    }

    //Same concept as UserData
    @GetMapping(value="/GroupData")
    public ModelAndView groupData(@RequestParam (required = false) String groupName, @RequestParam String buttonType, Model model){
        if(buttonType.equals("edit")){
            Group group = groupRepository.findByGroupName(groupName);
            if(group != null){
                model.addAttribute("group", group);
                Set<User> groupMembers = group.getGroupMembers();
                List<User> users = userRepository.findAll();
                users.removeAll(groupMembers);
                List<Framework> frameworks = frameworkRepository.findAll();
                Framework currentFramework = group.getFramework();
                frameworks.remove(currentFramework);
                model.addAttribute("roles", groupRoleRepository.findAll());
                model.addAttribute("users", users);
                model.addAttribute("groupMembers", group.getGroupMembers());
                model.addAttribute("edit", "edit");
                model.addAttribute("formAction", "/AdminEditGroup");
                model.addAttribute("frameworks", frameworks);
                model.addAttribute("currentFramework", currentFramework);
                return new ModelAndView("AdminModal");
            }else {
                model.addAttribute("error", "Error, Group: "+groupName+" no longer exists.");
                return new ModelAndView("Admin");
            }
        }else{
            model.addAttribute("group", "group");
            model.addAttribute("create", "create");
            model.addAttribute("users", userRepository.findAll());
            model.addAttribute("groupMembers", groupRepository.findAll());
            model.addAttribute("roles", groupRoleRepository.findAll());
            model.addAttribute("frameworks", frameworkRepository.findAll());
            model.addAttribute("formAction", "/AdminCreateGroup");
            return new ModelAndView("AdminModal");
        }

    }
    //Same concept
    @GetMapping(value="/FrameworkData")
    public ModelAndView frameworkData(@RequestParam (required = false) String frameworkName, @RequestParam String buttonType, Model model){
        if(buttonType.equals("edit")){
            Framework framework = frameworkRepository.findByFrameworkName(frameworkName);
            if(framework != null){
                model.addAttribute("framework", framework);
                model.addAttribute("edit", "edit");
                model.addAttribute("formAction", "/AdminEditFramework");
                Set<Focus> fociSet = framework.getFrameworkFoci();
                List<Focus> foci = new ArrayList<>(fociSet);
                List<Focus> allFoci = focusRepository.findAll();
                allFoci.removeAll(foci);
                model.addAttribute("foci", framework.getFrameworkFoci());
                model.addAttribute("allFoci", allFoci);
                return new ModelAndView("AdminModal");
            }else {
                model.addAttribute("error", "Error, Framework: "+frameworkName+" no longer exists.");
                return new ModelAndView("Admin");
            }
        }else{
            model.addAttribute("framework", "framework");
            model.addAttribute("create", "create");
            model.addAttribute("allFoci", focusRepository.findAll());
            model.addAttribute("formAction", "/AdminCreateGroup");
            return new ModelAndView("AdminModal");
        }

    }
    //Same concept
    @GetMapping(value="/FocusData")
    public ModelAndView focusData(@RequestParam (required = false) String focusName, @RequestParam String buttonType, Model model){
        if(!buttonType.equals("create")){
            Focus focus = focusRepository.findByFocusName(focusName);
            if(focus != null){
                model.addAttribute("focus", focus);
                model.addAttribute("edit", "edit");
                model.addAttribute("formAction", "/AdminEditFocus");
                return new ModelAndView("AdminModal");
            }else {
                model.addAttribute("error", "Error, Focus: "+focusName+" no longer exists.");
                return new ModelAndView("Admin");
            }
        }else{
            model.addAttribute("focus", "focus");
            model.addAttribute("create", "create");
            model.addAttribute("formAction", "/AdminCreateFocus");
            return new ModelAndView("AdminModal");
        }

    }

    //Gets the rating of a focus for a user. Used by the admin modal when editing a users rating
    @GetMapping(value="/FocusRating")
    @ResponseBody
    public BigDecimal focusRating(@RequestParam String username, @RequestParam String focusName, Model model){
        User user = userRepository.findByUserName(username);
        BigDecimal ratingToReturn = null;
        if(user != null){
            Focus focus = focusRepository.findByFocusName(focusName);
            if(focus != null){
                ratingToReturn = userRepository.getUserRating(user.getRating(focus), user.getUserId(), focus.getFocusId());
            }
            if(ratingToReturn == null){
                model.addAttribute("error", "Error, Focus or Rating no longer exists.");
            }
        }else {
            model.addAttribute("error", "Error, User: "+username+" no longer exists.");
        }
        return ratingToReturn;
    }

    //Deletes a user(s)
    @PostMapping(value="/AdminDeleteUser")
    public ModelAndView adminDeleteUser(@RequestParam String[] usernames, Model model){
        for(String username: usernames){
            User user = userRepository.findByUserName(username);
            if(user != null){
                userRepository.delete(user);
            }else{
                model.addAttribute("error", "Error, User: "+username+" no longer exists");
            }
        }
        return new ModelAndView("Admin");
    }

    //Creates a user from the data passed from the modal
    @PostMapping(value="/AdminCreateUser")
    @ResponseBody
    public String createUser(@RequestParam String username, @RequestParam String password, @RequestParam (required = false) String[] roles,
                           @RequestParam (required = false) String[] groups, @RequestParam (required = false) String[] foci,
                           @RequestParam (required = false) String[] ratings, Model model){
        if(userRepository.findByUserName(username) != null){
            return "Error, a user with this username already exists";
        }else{
            User user = new User(username, bCryptPasswordEncoder.encode(password));
            if(roles != null){
                Set<Role> roleList = roleService.findRoles(roles);
                if(roleList.size() > 0){
                    user.setSystemRoles(roleList);
                }
            }
            //Set a users rating if given
            if(foci != null && ratings != null){
                Set<Rating> ratingsSet = new HashSet<>();
                int index = 0;
                for(String focus: foci){
                    Focus myFocus = focusRepository.findByFocusName(focus);
                    if(myFocus != null){
                        Rating rating = new Rating(user, myFocus, new BigDecimal(ratings[index]));
                        ratingRepository.save(rating);
                    }
                    index++;
                }
            }
            //Adding groups to the user
            if(groups != null){
                Set<Group> groupList = groupService.findGroups(groups);
                for(Group group: groupList){
                    user.addGroup(group);
                }
            }
            userRepository.save(user);
        }
        return "success";
    }

    //roles and roleGroups correspond 1-1 (using the same index for both gives the correct combination
    @PostMapping(value = "/AdminEditUser")
    public ModelAndView adminEdit(@RequestParam String username, @RequestParam String password, @RequestParam (required = false) String[] foci,
                                  @RequestParam (required = false) String[] rating, @RequestParam (required = false) String[] roles,
                                  @RequestParam (required = false) String[] groups, @RequestParam (required = false) String[] systemRoles,
                                  @RequestParam (required = false) String[] roleGroups, Model model){
        User user = userRepository.findByUserName(username);
        if(user != null){
            BCryptPasswordEncoder bcrypt = new BCryptPasswordEncoder();
            //password is currently displayed using a placeholder of '*' characters.
            //value is set to '' by default as a users password cannot be retrieved (unless using cookies),
            //also allows to check if its been edited
            if(!password.equals("")){
                user.setPassword(bcrypt.encode(password));
            }
            Set<Group> groupList = new HashSet<>();
            Set<GroupUserRoles> groupRoleSet = new HashSet<>();
            if(roles != null){
                int count = 0;
                for(String role: roles){
                    GroupRole groupRole = groupRoleRepository.findByRoleName(role);
                    Group group = groupRepository.findByGroupName(roleGroups[count]);
                    count++;
                    if(groupRole != null && group != null){
                        GroupUserRoles newRole = new GroupUserRoles(groupRoleRepository.findByRoleName(role), group, user);
                        groupRoleSet.add(newRole);
                    }else{
                        model.addAttribute("error", "Error, Role: "+role+" no longer exists.");
                    }
                }
                user.setGroupUserRoles(groupRoleSet);
            }
            Set<Role> finalSystemRoles = new HashSet<>();
            if(systemRoles != null){
                for(String role: systemRoles){
                    Role newRole = roleRepository.findByRoleName(role);
                    if(newRole != null){
                        finalSystemRoles.add(newRole);
                    }
                }
            }
            user.setSystemRoles(finalSystemRoles);
            if(groups != null){
                for(String groupString: groups){
                    Group group = groupRepository.findByGroupName(groupString);
                    if(group != null){
                        groupList.add(group);
                        if(roles == null){
                            GroupUserRoles newRole = new GroupUserRoles(groupRoleRepository.findByRoleName("User"), group, user);
                            user.addGroupRole(newRole);
                        }
                    }else{
                        model.addAttribute("error", "Error, Group: "+groupString+" no longer exists.");
                    }
                }
            }
            user.setUsersGroups(groupList);
            //ensuring that the indices correspond and therefore the rating and foci correspond
            if(foci != null && rating != null && foci.length == rating.length){
                for(int i = 0; i < rating.length; i++){
                    Focus focus = focusRepository.findByFocusName(foci[i]);
                    Rating newRating = new Rating(user, focus, new BigDecimal(rating[i]));
                    ratingRepository.save(newRating);
                    user.addRating(newRating);
                }
            }
            userRepository.save(user);
        }else{
            model.addAttribute("error", "Error, User: "+username+" no longer exists.");
        }
        return new ModelAndView("Admin");
    }


    @PostMapping(value="/AdminCreateGroup", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ModelAndView createGroup(@RequestBody GroupWrapper request, Model model){
        String groupName = request.getGroupName();
        List<String> currentMembers = request.getCurrentMembers();
        String currentFramework = request.getCurrentFramework();
        List<String> currentRoles = request.getCurrentRoles();

        if(groupRepository.findByGroupName(groupName) == null){
            Set<User> members = new HashSet<>();
            Framework framework = null;
            if(currentMembers != null){
                for(String member: currentMembers){
                    User user = userRepository.findByUserName(member);
                    if(user != null){
                        members.add(user);
                        if(frameworkRepository.findByFrameworkName(currentFramework) != null){
                            framework = frameworkRepository.findByFrameworkName(currentFramework);
                            for(Focus focus: framework.getFrameworkFoci()){
                                Rating rating = new Rating(user, focus, BigDecimal.ONE);
                                user.addRating(rating);
                                ratingRepository.save(rating);
                            }
                        }
                        userRepository.save(user);
                    }
                }
            }
            //create group then add group roles
            Group group = new Group(groupName, members, framework);
            groupRepository.save(group);
            for(User user: members){
                GroupRole groupRole = groupRoleRepository.findByRoleName("User");
                GroupUserRoles role = new GroupUserRoles(groupRole, group, user);
                groupUserRoleRepository.save(role);
            }
        }else{
            model.addAttribute("error", "Error, a group with this name already exists.");
        }
        return new ModelAndView("Admin");
    }

    //Request body wrapped into a custom object, serializes more cleanly this way
    @PostMapping(value="/AdminEditGroup", consumes = MediaType.APPLICATION_JSON_VALUE)
        public ModelAndView editGroup(@RequestBody GroupWrapper request, Model model){
        String groupName = request.getGroupName();
        List<String> currentMembers = request.getCurrentMembers();
        String currentFramework = request.getCurrentFramework();
        List<String> currentRoles = request.getCurrentRoles();
        String originalName = request.getOriginalName();
        Group newGroup = groupRepository.findByGroupName(groupName);
        Group group = groupRepository.findByGroupName(originalName);

        //need to check if the name has changed and that a group with new name doesn't exist
        if(!originalName.equals(groupName)) {
            if (newGroup != null) {
                model.addAttribute("error", "Error, a group with this name already exists");
                return new ModelAndView("Admin");
            }else {
                group.setGroupName(groupName);
            }
        }
        Set<User> members = new HashSet<>();
        Set<GroupUserRoles> newRoles = new HashSet<>();
        //All members added to a group will be given a default role 'User'
        //member:role is 1:1 therefore the difference in size is the number
        //of default roles required
        if(currentMembers.size() != currentRoles.size()){
            int rolesToAdd = currentMembers.size() - currentRoles.size();
            for(int i = 0; i < rolesToAdd; i++){
                currentRoles.add("User");
            }
        }
        if(currentMembers.size() > 0){
            int count = 0;
            for(String groupMember: currentMembers){
                User member = userRepository.findByUserName(groupMember);
                if(member != null){
                    members.add(member);
                    GroupRole groupRole = groupRoleRepository.findByRoleName(currentRoles.get(count));
                    if(groupRole != null){
                        GroupUserRoles userRoles = new GroupUserRoles(groupRole, group, member);
                        newRoles.add(userRoles);
                    }
                    userRepository.save(member);
                    count++;
                }
            }
            group.setGroupMembers(members);
            group.setGroupUserRoles(newRoles);
        }
        //I think this is currently unnecessary to add ratings here as Peter wanted Ratings to be given to all Users when a foci is created
        if(currentFramework != null && !currentFramework.equals("")){
            if(frameworkRepository.findByFrameworkName(currentFramework) != null){
                group.setFramework(frameworkRepository.findByFrameworkName(currentFramework));
                for(User member: members){
                    for(Focus focus: frameworkRepository.findByFrameworkName(currentFramework).getFrameworkFoci()){
                        Rating rating = new Rating(member, focus, BigDecimal.ONE);
                        if(!member.hasRating(rating)) {
                            ratingRepository.save(rating);
                        }
                        userRepository.save(member);
                    }
                }
            }
        }
        groupRepository.save(group);
        return new ModelAndView("Admin");
    }

    @PostMapping(value="/AdminDeleteGroup")
    public ModelAndView removeGroup(@RequestParam String[] groupNames, Model model){
        for(String groupName: groupNames){
            if(groupRepository.findByGroupName(groupName) != null){
                groupRepository.delete(groupRepository.findByGroupName(groupName));
            }else{
                model.addAttribute("error", "");
            }
        }
        return new ModelAndView("Admin");
    }

    @PostMapping(value="/AdminCreateFramework")
    public ModelAndView createFramework(@RequestParam String frameworkName, @RequestParam (required = false) String[] currentFoci, Model model){
        if(frameworkRepository.findByFrameworkName(frameworkName) == null){
            Set<Focus> fociList = new HashSet<>();
            if(currentFoci != null){
                for(String focus: currentFoci){
                    if(focusRepository.findByFocusName(focus) != null){
                        fociList.add(focusRepository.findByFocusName(focus));
                    }
                }
            }
            frameworkRepository.save(new Framework(frameworkName, fociList));
        }else{
            model.addAttribute("error", "Error, a group with this name already exists.");
        }
        return new ModelAndView("Admin");
    }


    @PostMapping(value="/AdminEditFramework")
    public ModelAndView editFramework(@RequestParam String frameworkName, @RequestParam String originalName, @RequestParam (required = false) String[] currentFoci, Model model){
        //if the name of the framework has been edited
        Framework newFramework = frameworkRepository.findByFrameworkName(frameworkName);
        Framework framework = frameworkRepository.findByFrameworkName(originalName);
        if(!originalName.equals(frameworkName)){
            if(newFramework != null){
                model.addAttribute("error", "Error, a framework with this name already exists");
            }else{
                if(currentFoci != null){
                    for(String focus: currentFoci){
                        Focus myFocus = focusRepository.findByFocusName(focus);
                        if(myFocus != null && !framework.getFrameworkFoci().contains(myFocus)){
                            framework.addFocus(myFocus);
                            for(Group group: framework.getGroups()){
                                for(User user: group.getGroupMembers()){
                                    Rating rating = new Rating(user, myFocus, BigDecimal.ONE);
                                    user.addRating(rating);
                                    ratingRepository.save(rating);
                                }
                            }
                        }
                    }
                }
                framework.setFrameworkName(frameworkName);
                frameworkRepository.save(framework);
            }
        }else{
            Set<Focus> fociSet = new HashSet<>();
            if(currentFoci != null){
                for(String focus: currentFoci){
                    Focus myFocus = focusRepository.findByFocusName(focus);
                    if(myFocus != null && !framework.getFrameworkFoci().contains(myFocus)){ //add focus if it doesn't exist
                        framework.addFocus(myFocus);
                        //need to set ratings for users who belong to groups containing the framework w/ new foci
                        for(Group group: framework.getGroups()){
                            for(User user: group.getGroupMembers()){
                                Rating rating = new Rating(user, myFocus, BigDecimal.ONE);
                                user.addRating(rating);
                                ratingRepository.save(rating);
                            }
                        }
                    }
                }
                frameworkRepository.save(framework);
            }
        }
        return new ModelAndView("Admin");
    }

    @PostMapping(value="/AdminDeleteFramework")
    public ModelAndView removeFramework(@RequestParam String[] frameworkNames, Model model){
        for(String frameworkName: frameworkNames){
            if(frameworkRepository.findByFrameworkName(frameworkName) != null){
                frameworkRepository.delete(frameworkRepository.findByFrameworkName(frameworkName));
            }else{
                model.addAttribute("error", "Error, framework no longer exists");
            }
        }
        return new ModelAndView("Admin");
    }

    @PostMapping(value="/AdminCreateFoci")
    public ModelAndView createFoci(@RequestParam String focusName, @RequestParam String focusCategory,
                                   @RequestParam String focusExplanation, Model model){
        if(focusRepository.findByFocusName(focusName) == null){
            focusRepository.save(new Focus(focusName, focusCategory, focusExplanation));
        }else{
            model.addAttribute("error", "Error, a focus with this name already exists.");
        }
        return new ModelAndView("Admin");
    }

    @PostMapping(value="/AdminEditFoci")
    public ModelAndView editFoci(@RequestParam String focusName, @RequestParam String focusCategory, @RequestParam String focusExplanation,
                                 @RequestParam String originalName, Model model){
        Focus newFocus = focusRepository.findByFocusName(focusName);
        Focus focus = focusRepository.findByFocusName(originalName);
        if(!originalName.equals(focusName)){
            if(newFocus != null){
                model.addAttribute("error", "Error, a focus with this name already exists");
                //if a focus with a new name does not exist
            }else{
                focus.setFocusName(focusName);
                focus.setFocusExplanation(focusExplanation);
                focus.setFocusCategory(focusCategory);
                focusRepository.save(focus);
            }
        }else{
            focus.setFocusCategory(focusCategory);
            focus.setFocusExplanation(focusExplanation);
            focusRepository.save(focus);
        }
        return new ModelAndView("Admin");
    }

    //Deletes a focus/foci
    @PostMapping(value="/AdminDeleteFoci")
    public ModelAndView removeFoci(@RequestParam String[] focusNames, Model model){
        for(String focusName: focusNames){
            if(focusRepository.findByFocusName(focusName) != null){
                focusRepository.delete(focusRepository.findByFocusName(focusName));
            }else{
                model.addAttribute("error", "Error, one or more foci no longer exists");
            }
        }
        return new ModelAndView("Admin");
    }

    //Simply retrieves roles to populate a selectpicker
    @GetMapping("/GetRoles")
    @ResponseBody
    public List<String> getRoles(@RequestParam String groupName){
        List<String> output = new LinkedList<>();
        for(GroupRole groupRole: groupRoleRepository.findAll()) {
            output.add(groupRole.getName());
        }
        return output;
    }
}
