package vn.azteam.tpf.service.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vn.azteam.tpf.domain.TBCrop;
import vn.azteam.tpf.repository.UserRepository;
import vn.azteam.tpf.repository.search.UserSearchRepository;
import vn.azteam.tpf.service.*;
import vn.azteam.tpf.service.dto.TBCropDTO;
import vn.azteam.tpf.service.dto.TBRoleDTO;
import vn.azteam.tpf.service.dto.UserDTO;
import vn.azteam.tpf.service.mapper.UserMapper;
import vn.azteam.tpf.web.rest.UserResource;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


@Service
@Transactional(readOnly = true)
public class UserRoleUtil {
    private final Logger log = LoggerFactory.getLogger(UserResource.class);

    private final UserService userService;

    private final UserRepository userRepository;

    private final UserSearchRepository userSearchRepository;

    private final TBEquipmentOfCustomerQueryService tBEquipmentOfCustomerQueryService;

    private final UserMapper userMapper;

    private final TBCropService tBCropService;

    private final TBRoleService tbRoleService;

    private final EntityManager em;

    public UserRoleUtil(@Lazy UserService userService,
                        UserRepository userRepository,
                        TBEquipmentOfCustomerQueryService tBEquipmentOfCustomerQueryService,
                        UserSearchRepository userSearchRepository,
                        UserMapper userMapper,
                        TBCropService tBCropService,
                        TBRoleService tbRoleService, EntityManager em) {

        this.userService = userService;
        this.userRepository = userRepository;
        this.tBEquipmentOfCustomerQueryService = tBEquipmentOfCustomerQueryService;
        this.userSearchRepository = userSearchRepository;
        this.userMapper = userMapper;
        this.tBCropService = tBCropService;
        this.tbRoleService = tbRoleService;
        this.em = em;
    }

    public List<Long> getListCropIdAssignByCurrentUser(Long userId) {

        String query = "SELECT DISTINCT (ass.tb_crops_id) FROM tb_assignment as ass\n" +
            "where ass.tb_detail_users_id = :userId";

        Query envStandardQuery = em.createNativeQuery(query);
        envStandardQuery.setParameter("userId", userId);
        List<BigInteger> cropIds = envStandardQuery.getResultList();

        List<Long> finalResult = new ArrayList<>();
        for(BigInteger cropId : cropIds ) {
            finalResult.add(cropId.longValue());
        }
        return finalResult;
    }

    public List<Long> getListUserIdByCropId(Long cropId) {

        String query = "SELECT DISTINCT (du.id) FROM tb_assignment as ass\n" +
            "join tb_detail_user as du\n" +
            "on du.id = ass.tb_detail_users_id\n" +
            "where ass.tb_crops_id = :cropId";

        Query usersOnCropQuery = em.createNativeQuery(query);
        usersOnCropQuery.setParameter("cropId", cropId);
        List<BigInteger> userIds = usersOnCropQuery.getResultList();

        List<Long> finalResult = new ArrayList<>();
        for(BigInteger userId : userIds ) {
            finalResult.add(userId.longValue());
        }
        return finalResult;
    }

    public boolean currentUserHasPermissionByCustomerId(Long cropId){
        boolean check = false;
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        Optional<TBCropDTO> tbCropDTO = tBCropService.findOne(cropId);
        if(tbCropDTO.isPresent() && tbCropDTO.get().getTbCustomerId() == currentUser.getCustomerId()) {
            check = true;
        }
        return check;
    }

    public boolean currentUserHasPermissionByCropId(Long cropId){
        boolean check = true;
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        Long currentUserId = currentUser.getId();
        if(currentUser.getCustomerId() != null) {
            TBRoleDTO currentUserRole = tbRoleService.findOne(currentUser.getRoleId()).get();
            List<Long> listCropId = tBCropService.getAllCropIdByCustomer(currentUser.getCustomerId());
            if(!currentUserRole.getIsAllCrop()) {
                listCropId = getListCropIdAssignByCurrentUser(currentUserId);
            }
            check = listCropId.contains(cropId);
        }
        return check;
    }

    public boolean currentUserHasPermissionByEntityId(Long entityId){
        boolean check = true;
        UserDTO currentUser = userService.getCurrentUserDTO().get();
        Long currentUserId = currentUser.getId();

        if(!userService.getListRoleAllCrop().contains(currentUser.getRoleId())) {
            List<Long> listEntityId = getListEntityIdByCurrentUser(currentUserId);
            check = listEntityId.contains(entityId);
        }
        return check;
    }

    public List<Long> getListEntityIdByCurrentUser(Long userId) {

        String query = "SELECT DISTINCT (tbc.tb_entity_id) FROM tb_assignment as ass\n" +
            " inner join tb_crop as tbc " +
            " on tbc.id = ass.tb_crops_id " +
            " where ass.tb_detail_users_id = :userId";

        Query envStandardQuery = em.createNativeQuery(query);
        envStandardQuery.setParameter("userId", userId);
        List<BigInteger> entityIds = envStandardQuery.getResultList();

        List<Long> finalResult = new ArrayList<>();
        for(BigInteger entityId : entityIds ) {
            finalResult.add(entityId.longValue());
        }
        return finalResult;
    }
}
