package eu.eudat.logic.managers;

import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.UserDMP;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.models.data.invitation.Invitation;
import eu.eudat.models.data.security.Principal;
import eu.eudat.models.data.userinfo.UserInfoInvitationModel;
import eu.eudat.data.query.items.item.userinfo.UserInfoRequestItem;
import eu.eudat.queryable.QueryableList;
import eu.eudat.logic.services.ApiContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Component
public class InvitationsManager {

    private ApiContext apiContext;

    @Autowired
    public InvitationsManager(ApiContext apiContext) {
        this.apiContext = apiContext;
    }

    public void inviteUsers(Invitation invitation, Principal principal) throws Exception {
        UserInfo principalUser = new UserInfo();
        principalUser.setId(principal.getId());
        List<UserInfoInvitationModel> alreadySignedInUsers = invitation.getUsers().stream().filter(item -> item.getId() != null).collect(Collectors.toList());
        List<UserInfo> alreadySignedInUsersEntities = alreadySignedInUsers.stream().map(item -> item.toDataModel()).collect(Collectors.toList());
        List<UserDMP> userInfoToUserDmp = new LinkedList<>();
        for (UserInfo userInfo : alreadySignedInUsersEntities) {
            UserDMP userDMP = new UserDMP();
            userDMP.setUser(userInfo);
            userInfoToUserDmp.add(userDMP);
        }
        DMP dataManagementPlan = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(invitation.getDataManagementPlan());
        apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), apiContext.getUtilitiesService().getMailService(), invitation.getUsers().stream().map(item -> item.toDataModel()).collect(Collectors.toList()), dataManagementPlan, principalUser);
        apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userInfoToUserDmp, dataManagementPlan);
    }

    public List<UserInfoInvitationModel> getUsers(UserInfoRequestItem userInfoRequestItem) throws InstantiationException, IllegalAccessException {
        QueryableList<UserInfo> users = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().getWithCriteria(userInfoRequestItem.getCriteria());
        List<UserInfoInvitationModel> userModels = users.select(item -> new UserInfoInvitationModel().fromDataModel(item));
        return userModels;
    }

    public UUID assignUserAcceptedInvitation(UUID invitationID, Principal principal) throws UnauthorisedException {
        eu.eudat.data.entities.Invitation invitation = apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().find(invitationID);
        if (invitation == null)
            throw new UnauthorisedException("There is no Data Management Plan assigned to this Link");
        if (invitation.getAcceptedInvitation()) throw new UnauthorisedException("This Url Has Expired");
        UserInfo invitedUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId());
        UserDMP userDMP = new UserDMP();
        userDMP.setUser(invitedUser);
        userDMP.setDmp(invitation.getDmp());
        userDMP.setRole(UserDMP.UserDMPRoles.USER.getValue());
        DMP datamanagementPlan = invitation.getDmp();
        apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().createOrUpdate(userDMP);
        apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userDMP, datamanagementPlan);
        invitation.setAcceptedInvitation(true);
        apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().createOrUpdate(invitation);
        return datamanagementPlan.getId();
    }
}
