package eu.dnetlib.uoanotificationservice.utils;

import eu.dnetlib.uoaauthorizationlibrary.security.AuthorizationService;
import eu.dnetlib.uoanotificationservice.dao.NotificationDAO;
import org.apache.commons.validator.routines.EmailValidator;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

@Component("Utils")
public class Utils {

    Logger logger = Logger.getLogger(Utils.class);
    private final AuthorizationService authorizationService;
    private final NotificationDAO notificationDAO;
    private final EmailValidator emailValidator;

    @Autowired
    public Utils(AuthorizationService authorizationService, NotificationDAO notificationDAO) {
        this.authorizationService = authorizationService;
        this.notificationDAO = notificationDAO;
        this.emailValidator = EmailValidator.getInstance();
    }

    public boolean canRead(String id) {
        Set<String> groups = new HashSet<>(authorizationService.getRoles());
        groups.add("all");
        groups.add(authorizationService.getEmail().toLowerCase());
        return notificationDAO.findByIdAndUserNotAndGroupsIn(id, authorizationService.getAaiId(), groups).isPresent();
    }

    public boolean hasValidGroups(Set<String> groups, String stakeholderType) {
        Set<String> roles = new HashSet<>(authorizationService.getRoles());
        if(stakeholderType != null) {
            roles.add(authorizationService.curator(stakeholderType));
        }
        Set<String> check = new HashSet<>(groups);
        Set<String> types = getCuratorTypes(roles);
        if(roles.contains(authorizationService.PORTAL_ADMIN)) {
            return true;
        } else if(groups.contains("all")) {
            return false;
        }
        return check.stream().filter(group -> {
            if(emailValidator.isValid(group)) {
                return false;
            }
            for (String type : types) {
                if (group.contains(type)) {
                    return false;
                }
            }
            return true;
        }).allMatch(roles::contains);
    }

    private Set<String> getCuratorTypes(Set<String> roles) {
        return roles.stream().filter(role -> role.contains("CURATOR_")).
                map(curator -> curator.replace("CURATOR_", "")).collect(Collectors.toSet());
    }
}
