package fi.hsl.parkandride.core.service;

import static fi.hsl.parkandride.core.domain.Permission.USER_CREATE;
import static fi.hsl.parkandride.core.domain.Permission.USER_VIEW;
import static fi.hsl.parkandride.core.domain.Role.ADMIN;
import static fi.hsl.parkandride.core.domain.Role.OPERATOR;
import static fi.hsl.parkandride.core.domain.Role.OPERATOR_API;
import static fi.hsl.parkandride.core.service.AuthenticationService.authorize;

import fi.hsl.parkandride.core.back.UserRepository;
import fi.hsl.parkandride.core.domain.*;

public class UserService {

    private final AuthenticationService authenticationService;

    private final UserRepository userRepository;

    private final ValidationService validationService;

    public UserService(UserRepository userRepository, AuthenticationService authenticationService, ValidationService validationService) {
        this.userRepository = userRepository;
        this.authenticationService = authenticationService;
        this.validationService = validationService;
    }

    public SearchResults<User> findUsers(UserSearch search, User currentUser) {
        authorize(currentUser, search, USER_VIEW);

        return userRepository.findUsers(search);
    }


    @TransactionalWrite
    public User createUser(NewUser newUser, User currentUser) {
        authorize(currentUser, newUser, USER_CREATE);

        if (currentUser.role != ADMIN && !isOperatorRole(newUser.role)) {
            throw new ValidationException(new Violation("IllegalRole", "role", "Expected an operator role, got " + newUser.role));
        }

        validationService.validate(newUser);
        return createUserNoValidate(newUser);
    }

    @TransactionalWrite
    public User createUserNoValidate(NewUser newUser) {
        UserSecret userSecret = new UserSecret();
        if (!newUser.role.perpetualToken) {
            validatePassword(newUser.password);
            userSecret.password = authenticationService.encryptPassword(newUser.password);

        }
        validateOperator(newUser);

        userSecret.user = new User(newUser);
        userSecret.user.id = userRepository.insertUser(userSecret);
        return userSecret.user;
    }

    private void validateOperator(NewUser newUser) {
        if (isOperatorRole(newUser.role) && newUser.operatorId == null) {
            throw new ValidationException(new Violation("OperatorRequired", "operator", "Operator is required for operator user"));
        }
    }

    private void validatePassword(String password) {
        if (!isValidPassword(password)) {
            throw new ValidationException(new Violation("BadPassword", "password", "Expected a password of length >= 8"));
        }
    }

    private boolean isValidPassword(String password) {
        if (password == null) {
            return false;
        }
        // TODO
        return true;
    }

    private boolean isOperatorRole(Role role) {
        return role == OPERATOR || role == OPERATOR_API;
    }
}

@@ -1371,251 +1371,30 @@
     
-if (currentUser.role != ADMIN && !isOperatorRole(newUser.role)) %7B%0A            throw new ValidationException(new Violation(%22IllegalRole%22, %22role%22, %22Expected an operator role, got %22 + newUser.role));%0A        %7D%0A%0A        validationService.validate(
+validate(currentUser, 
 newU
@@ -1630,56 +1630,8 @@
 ) %7B%0A
-            validatePassword(newUser.password);%0A
     
@@ -1717,17 +1717,16 @@
 sword);%0A
-%0A
         
@@ -1731,44 +1731,8 @@
   %7D%0A
-        validateOperator(newUser);%0A%0A
     
@@ -1840,16 +1840,16 @@
 ecret);%0A
-
         
@@ -1871,32 +1871,500 @@
 et.user;%0A    %7D%0A%0A
+    private void validate(User currentUser, NewUser newUser) %7B%0A        if (currentUser.role != ADMIN && !isOperatorRole(newUser.role)) %7B%0A            throw new ValidationException(new Violation(%22IllegalRole%22, %22role%22, %22Expected an operator role, got %22 + newUser.role));%0A        %7D%0A%0A        validationService.validate(newUser);%0A        if (!newUser.role.perpetualToken) %7B%0A            validatePassword(newUser.password);%0A        %7D%0A        validateOperator(newUser);%0A    %7D%0A%0A
     private void

move validation logic in UserService to createUser