class AccessRequestService {

    public boolean isApprovalNeeded(AccessRequest request) throws Exception{
        logger.info("Checking whether user " + request.getRequestorId() + " requires approval for request " + request.getId());

        //Approvers never require approval
        if(gatekeeperRoleService.isApprover()) {
            logger.info("User " + request.getRequestorId() + " is an approver. No approval required.");
            return false;
        }
        //We have to associate the policy to the SDLC of the requested account. The name of the account provided by the ui will not always be "dev" "qa" or "prod", but they will need to associate with those SDLC's
        Account theAccount = accountInformationService.getAccountByAlias(request.getAccount());

        Map<String, RoleMembership> roleMemberships = gatekeeperRoleService.getRoleMemberships();
        logger.info("Retrieving approval policy for user: " + request.getRequestorId());
        Map<String, AppApprovalThreshold> approvalThresholds = approvalThreshold.getApprovalPolicy(roleMemberships);
        logger.info("Approval thresholds for request " + request.getId() + ": " + approvalThresholds);

        String application = request.getAwsRdsInstances().get(0).getApplication();
        String accountSdlc = theAccount.getSdlc().toLowerCase();
        Integer approvalRequiredThreshold = overridePolicy.getMaxDays();
        if(approvalThresholds.containsKey(application)) {
            Map<RoleType, Map<String, Integer>> appApprovalThresholds = approvalThresholds.get(application).getAppApprovalThresholds();
            for(UserRole userRole : request.getRoles()){
                if (appApprovalThresholds.containsKey(RoleType.valueOf(userRole.getRole().toUpperCase())) &&
                        appApprovalThresholds.get(RoleType.valueOf(userRole.getRole().toUpperCase())).containsKey(accountSdlc) &&
                        appApprovalThresholds.get(RoleType.valueOf(userRole.getRole().toUpperCase())).get(accountSdlc) < approvalRequiredThreshold) {
                    approvalRequiredThreshold = appApprovalThresholds.get(RoleType.valueOf(userRole.getRole().toUpperCase())).get(accountSdlc);
                }
            }
            if(request.getDays() <= approvalRequiredThreshold) {
                logger.info("User " + request.getRequestorId() + " does not require approval for request " + request.getId() + ". Request duration: " + request.getDays() + ". Threshold: " + approvalRequiredThreshold);
                return false;
            } else {
                logger.info("User " + request.getRequestorId() + " requires approval for request " + request.getId() + ". Request duration: " + request.getDays() + ". Threshold: " + approvalRequiredThreshold);
                return true;
            }
        }

        logger.info("User " + request.getRequestorId() + " is not a member of any " + application + " AD groups.");
        //Always require approval if the user is not a member of the application's AD groups
        return true;
    }

    @Autowired public  AccessRequestService(TaskService taskService,
                                AccessRequestRepository accessRequestRepository,
                                GatekeeperRoleService gatekeeperRoleService,
                                RuntimeService runtimeService,
                                HistoryService historyService,
                                GatekeeperApprovalProperties gatekeeperApprovalProperties,
                                AccountInformationService accountInformationService,
                                GatekeeperOverrideProperties overridePolicy,
                                DatabaseConnectionService databaseConnectionService,
                                EntityManager entityManager);

}