package jnpf.certificate.helper;

import cn.hutool.core.collection.CollectionUtil;
import jnpf.base.ActionResult;
import jnpf.permission.StoreApi;
import jnpf.permission.V2OrganizeApi;
import jnpf.permission.V2PositionApi;
import jnpf.permission.V2UserApi;
import jnpf.permission.dto.v2.organzie.BaseOrganizeQueryDTO;
import jnpf.permission.dto.v2.user.QueryUserOrgRelationDTO;
import jnpf.permission.dto.v2.user.QueryUserBaseRelationDTO;
import jnpf.permission.eum.v2.UserWorkStatusEnums;
import jnpf.permission.vo.store.StoreInfoDetailVO;
import jnpf.permission.vo.v2.organzie.OrganizeBaseInfoVO;
import jnpf.permission.vo.v2.organzie.OrganizeGeneralDetailVO;
import jnpf.permission.vo.v2.position.PositionBaseInfoVO;
import jnpf.permission.vo.v2.user.UserBaseInfoVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.permission.vo.v2.user.UserBaseRelationSimpleVO;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class OrganizationHelper {
    @Autowired
    private V2OrganizeApi v2OrganizeApi;
    @Autowired
    private V2PositionApi v2PositionApi;
    @Autowired
    private V2UserApi v2UserApi;
    @Autowired
    private StoreApi storeApi;

    public List<String> getUserIdsByOrgId(String orgId){
        if(StringUtil.isBlank(orgId)){
            return Collections.emptyList();
        }
        ActionResult<List<String>> actionResult = v2UserApi.listUserIdsByOrganizeId(orgId, UserProvider.getUser().getTenantId());
        return getDataByResult(actionResult,"v2UserApi.listUserIdsByOrganizeId",orgId)
                .orElse(Collections.emptyList());
    }

    /**
     * 根据多个userId查询多个用户信息
     * @return
     */
    public Map<String, UserBaseRelationSimpleVO> getUserBaseRelationMapByOrgId(String orgId){
        if(StringUtil.isBlank(orgId)){
            return Collections.emptyMap();
        }
        QueryUserBaseRelationDTO dto = new QueryUserBaseRelationDTO();
        dto.setTenantId(UserProvider.getUser().getTenantId());
        dto.setOrgIds(Collections.singletonList(orgId));
        return getUserBaseRelationMapByUserIds(dto);
    }

    public Map<String, UserBaseRelationSimpleVO> getUserBaseRelationMapByUserIds(Collection<String> userIds){
        if(CollectionUtil.isEmpty(userIds)){
            return Collections.emptyMap();
        }
        QueryUserBaseRelationDTO dto = new QueryUserBaseRelationDTO();
        dto.setTenantId(UserProvider.getUser().getTenantId());
        dto.setUserIds(userIds);
        return getUserBaseRelationMapByUserIds(dto);
    }

    public Map<String, UserBaseRelationSimpleVO> getUserBaseRelationMapByUserIds(QueryUserBaseRelationDTO dto){
        if(Objects.isNull(dto)){
            return Collections.emptyMap();
        }
        dto.setTenantId(UserProvider.getUser().getTenantId());
        ActionResult<List<UserBaseRelationSimpleVO>> actionResult = v2UserApi.queryUserBaseRelationList(dto);
        Optional<List<UserBaseRelationSimpleVO>> listOptional = getDataByResult(actionResult,"v2UserApi.queryUserBaseRelationList",dto);
        return listOptional.map(l->l.stream()
                        .filter(item -> StringUtil.isNotBlank(item.getUserId()))
                        .collect(Collectors.toMap(UserBaseRelationSimpleVO::getUserId, item -> item, (v1, v2) -> v1)))
                .orElse(Collections.emptyMap());
    }

    public Map<String, UserBoundVO> getUserPrimaryBoundBatch(Collection<String> userIds) {
        if(CollectionUtil.isEmpty(userIds)){
            return Collections.emptyMap();
        }
        ActionResult<List<UserBoundVO>> actionResult = v2UserApi.getUserPrimaryBoundBatch(new ArrayList<>(userIds),UserProvider.getUser().getTenantId());
        Optional<List<UserBoundVO>> listOptional = getDataByResult(actionResult,"v2UserApi.getUserPrimaryBoundBatch",userIds);
        return listOptional
                .map(l->l.stream()
                .collect(Collectors.toMap(UserBoundVO::getId, item -> item, (v1, v2) -> v1)))
                .orElse(Collections.emptyMap());
    }

    public Map<String,UserBoundVO> getAllUserInfoBatch(Collection<String> userIds){
        if(CollectionUtil.isEmpty(userIds)){
            return Collections.emptyMap();
        }
        ActionResult<List<UserBoundVO>> actionResult = v2UserApi.getAllUserInfoBatch(new ArrayList<>(userIds),UserProvider.getUser().getTenantId());
        Optional<List<UserBoundVO>> listOptional = getDataByResult(actionResult,"v2UserApi.getAllUserInfoBatch",userIds);
        return listOptional.map(l->l.stream()
                .collect(Collectors.toMap(UserBoundVO::getId,u->u)))
                .orElse(Collections.emptyMap());
    }

    public Map<String,List<UserBoundVO>> buildUserBoundVOs(Collection<String> orgIds,
                                                           boolean hasChild,
                                                           List<UserWorkStatusEnums> notUserWorkStatusEnumsList,
                                                           String tenantId) {
        if(CollectionUtil.isEmpty(orgIds)){
            return Collections.emptyMap();
        }
        ActionResult<List<UserBoundVO>> actionResult = v2UserApi.listTargetOrganizesOrHaveChild(new ArrayList<>(orgIds),hasChild,notUserWorkStatusEnumsList,tenantId);

        Optional<List<UserBoundVO>> listOptional = getDataByResult(actionResult,"v2UserApi.listTargetOrganizesOrHaveChild",orgIds,hasChild,notUserWorkStatusEnumsList,tenantId);
        return listOptional.map(l->l.stream()
                        .collect(Collectors.groupingBy(UserBoundVO::getOrganizeId)))
                .orElse(Collections.emptyMap());
    }

    public Map<String, PositionBaseInfoVO> buildPositionBaseInfos(Collection<String> positionIds) {
        if(CollectionUtil.isEmpty(positionIds)){
            return Collections.emptyMap();
        }
        String tenantId = UserProvider.getUser().getTenantId();
        ActionResult<List<PositionBaseInfoVO>> actionResult = v2PositionApi.listPositionBaseInfoByIds(new ArrayList<>(positionIds), tenantId);

        Optional<List<PositionBaseInfoVO>> positionBaseInfoVOS = getDataByResult(actionResult,"v2PositionApi.listPositionBaseInfoByIds",positionIds);
        return positionBaseInfoVOS.map(l->l.stream()
                .collect(Collectors.toMap(PositionBaseInfoVO::getId, item -> item, (v1, v2) -> v1)))
                .orElse(Collections.emptyMap());
    }

    public Map<String, OrganizeGeneralDetailVO> buildOrganizeGenerals(Collection<String> orgIds) {
        if(CollectionUtil.isEmpty(orgIds)){
            return Collections.emptyMap();
        }
        ActionResult<List<OrganizeGeneralDetailVO>> listActionResult = v2OrganizeApi.organizesByOrganizeIds(new ArrayList<>(orgIds));

        Optional<List<OrganizeGeneralDetailVO>> listOptional = getDataByResult(listActionResult,"v2OrganizeApi.organizesByOrganizeIds",orgIds);
        return listOptional.map(l->l.stream()
                .collect(Collectors.toMap(OrganizeGeneralDetailVO::getId, item -> item, (v1, v2) -> v1)))
                .orElse(Collections.emptyMap());
    }

    public Map<String, List<StoreInfoDetailVO>> buildStoreInfoDetailsByFranchiseeId(String ...franchiseeId) {
        ActionResult<List<StoreInfoDetailVO>> listActionResult = storeApi.listInfoDetailsByFranchiseeIds(List.of(franchiseeId));

        Optional<List<StoreInfoDetailVO>> listOptional = getDataByResult(listActionResult,"storeApi.listInfoDetailsByFranchiseeIds", (Object) franchiseeId);
        return listOptional.map(storeInfoDetailVOS -> storeInfoDetailVOS.stream()
                .collect(Collectors.groupingBy(StoreInfoDetailVO::getFranchiseeId)))
                .orElse(Collections.emptyMap());
    }

    public Map<String,List<String>> buildUserIdsByOrgIds(Collection<String> orgIds,boolean orgIdsEmptyQueryAll,String storeTag){
        if(CollectionUtil.isEmpty(orgIds) && !orgIdsEmptyQueryAll){
            return Collections.emptyMap();
        }

        QueryUserOrgRelationDTO queryUserOrgRelationDTO = new QueryUserOrgRelationDTO(orgIdsEmptyQueryAll,orgIds,UserProvider.getUser().getTenantId(),storeTag);
        ActionResult<Map<String, List<String>>> actionResult = v2UserApi.listUserIdsByQueryDTO(queryUserOrgRelationDTO);
        return getDataByResult(actionResult,"v2UserApi.listUserIdsByQueryDTO",queryUserOrgRelationDTO)
                .orElse(Collections.emptyMap());
    }

    /**
     * 根据用户id获取组织id。key为userId,value为组织id
     * @param userIds
     * @return
     */
    public Map<String,String> buildOrgIdsByUserIds(Collection<String> userIds,String tenantId){
        if(CollectionUtil.isEmpty(userIds)){
            return Collections.emptyMap();
        }
        ActionResult<Map<String, String>> actionResult = v2UserApi.listOrganizeIdsByUserIds(userIds,tenantId);
        return getDataByResult(actionResult,"v2UserApi.listOrganizeIdsByUserIds",userIds)
                .orElse(Collections.emptyMap());
    }


    /**
     * 根据用户id获取用户基础信息，用户id，名称，组织id
     * @param userIds
     * @return
     */
    public Map<String, UserBaseInfoVO> buildUserBaseInfoByUserIds(Collection<String> userIds, String tenantId){
        if(CollectionUtil.isEmpty(userIds)){
            return Collections.emptyMap();
        }
        ActionResult<List<UserBaseInfoVO>> actionResult = v2UserApi.listUserBaseInfoByUserIds(userIds,tenantId);
        return getDataByResult(actionResult,"v2UserApi.listUserBaseInfoByUserIds",userIds,tenantId)
                .orElse(Collections.emptyList())
                .stream()
                .collect(Collectors.toMap(UserBaseInfoVO::getUserId, item -> item));
    }

    public Map<String, OrganizeBaseInfoVO> buildBaseOrganizeVO(Collection<String> orgIds,String tenantId) {
        if(CollectionUtil.isEmpty(orgIds)){
            return Collections.emptyMap();
        }
        ActionResult<List<OrganizeBaseInfoVO>> listActionResult = v2OrganizeApi.baseOrganizesByOrganizeIds(orgIds,tenantId);

        Optional<List<OrganizeBaseInfoVO>> listOptional = getDataByResult(listActionResult,"v2OrganizeApi.baseOrganizesByOrganizeIds",orgIds);
        return listOptional.map(l->l.stream()
                        .collect(Collectors.toMap(OrganizeBaseInfoVO::getId, item -> item)))
                .orElse(Collections.emptyMap());
    }


    public Map<String, OrganizeBaseInfoVO> buildBaseOrganizeVO(Collection<String> orgIds,String storeTag,String tenantId) {
        if(CollectionUtil.isEmpty(orgIds) && StringUtil.isBlank(storeTag)){
            return Collections.emptyMap();
        }
        BaseOrganizeQueryDTO dto = new BaseOrganizeQueryDTO();
        dto.setOrganizeIds(orgIds);
        dto.setStoreTag(storeTag);
        dto.setTenantId(tenantId);
        dto.setQueryParentName(true);
        ActionResult<List<OrganizeBaseInfoVO>> listActionResult = v2OrganizeApi.baseOrganizesByQueryDTO(dto);

        Optional<List<OrganizeBaseInfoVO>> listOptional = getDataByResult(listActionResult,"v2OrganizeApi.baseOrganizesByOrganizeIds",orgIds);
        return listOptional.map(l->l.stream()
                        .collect(Collectors.toMap(OrganizeBaseInfoVO::getId, item -> item)))
                .orElse(Collections.emptyMap());
    }

    private <T>Optional<T> getDataByResult(ActionResult<T> actionResult,String url,Object...params) {
        if(Objects.isNull(actionResult)){
            log.error("{} return null.params:{}",url,params);
            return Optional.empty();
        }
        if(actionResult.getCode() != 200){
            log.error("{} return code is not 200.actionResult:{},params:{}",url,actionResult,params);
            return Optional.empty();
        }
        return Optional.of(actionResult.getData());
    }
}
