package com.github.wxiaoqi.security.admin.biz;

import com.github.wxiaoqi.security.admin.entity.AppUserDetail;
import com.github.wxiaoqi.security.admin.entity.UserProfileDisplay;
import com.github.wxiaoqi.security.admin.mapper.UserProfileDisplayMapper;
import com.github.wxiaoqi.security.admin.vo.UserProfileDisplayVo;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.xxfc.platform.universal.entity.Dictionary;
import com.xxfc.platform.universal.feign.ThirdFeign;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

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

/**
 * @author libin
 * @version 1.0
 * @description
 * @data 2019/12/24 17:06
 */
@Transactional(rollbackFor = Exception.class)
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserProfileDisplayBiz extends BaseBiz<UserProfileDisplayMapper, UserProfileDisplay> {
    /**
     * 字典查询type
     */
    @Value("${large.screen.type:LARGE_SCREEN_DISPLAY}")
    private String largeScreenType;
    /**
     * 字典查询code
     */
    @Value("${large.screen.member.code:LARGE_SCREEN_DISPLAY_EMEMBER_CONSTANT}")
    private String largeScreenCode;
    private final AppUserDetailBiz appUserDetailBiz;
    private final ThirdFeign thirdFeign;
    private static final Integer GUANG_DONG_CODE = 440000;

    public UserProfileDisplayVo findUserProfileData() {
        UserProfileDisplayVo userProfileDisplayVo = new UserProfileDisplayVo();
        //1.查询固定数据
        List<UserProfileDisplay> userProfileDisplays = mapper.selectAll();
        //2.查询真实数据
        List<AppUserDetail> appUserDetails = appUserDetailBiz.findAllUsers();
        //3.包装数据
        List<UserProfileDisplay> wrapUserProfileDisplays = wrapToUserProfileDisplay(appUserDetails);
        if (CollectionUtils.isNotEmpty(wrapUserProfileDisplays)) {
            wrapUserProfileDisplays = aggreationForUserProfileDisplayData(userProfileDisplays, wrapUserProfileDisplays);
        }
        //4.查询固定会员数
        Dictionary dictionary = thirdFeign.findDictionaryByTypeAndCode(largeScreenType, largeScreenCode);
        if (Objects.nonNull(dictionary) && StringUtils.hasText(dictionary.getDetail())) {
            String memberNumStr = dictionary.getDetail();
            long memberNums = Integer.valueOf(memberNumStr);
            userProfileDisplayVo.setMembersNum(memberNums);
        }
        wrapUserProfileDisplay(wrapUserProfileDisplays, userProfileDisplayVo);
        userProfileDisplayVo.setUserProfileDisplays(wrapUserProfileDisplays);
        return userProfileDisplayVo;
    }

    private List<UserProfileDisplay> aggreationForUserProfileDisplayData(List<UserProfileDisplay> baseuserProfileDisplays, List<UserProfileDisplay> wrapUserProfileDisplays) {
        Map<Integer, UserProfileDisplay> userProfileMap = wrapUserProfileDisplays.stream().collect(Collectors.toMap(UserProfileDisplay::getProvinceCode, Function.identity()));
        for (UserProfileDisplay baseuserProfileDisplay : baseuserProfileDisplays) {
            Integer provinceCode = baseuserProfileDisplay.getProvinceCode();
            UserProfileDisplay userProfileDisplay = userProfileMap.get(provinceCode);
            if (Objects.isNull(userProfileDisplay)) {
                continue;
            }
            int userNums = baseuserProfileDisplay.getUsersNum() + userProfileDisplay.getUsersNum();
            long memberNums = baseuserProfileDisplay.getMemberNums() + userProfileDisplay.getMemberNums();
            baseuserProfileDisplay.setUsersNum(userNums);
            baseuserProfileDisplay.setMemberNums(memberNums);
        }
        return baseuserProfileDisplays;
    }

    private UserProfileDisplayVo wrapUserProfileDisplay(List<UserProfileDisplay> userProfileDisplays, UserProfileDisplayVo userProfileDisplayVo) {
        long membersNum = 0;
        long usersNum = 0;
        for (UserProfileDisplay userProfileDisplay : userProfileDisplays) {
            usersNum = usersNum + userProfileDisplay.getUsersNum();
            membersNum = membersNum + userProfileDisplay.getMemberNums();
        }
        membersNum = membersNum + userProfileDisplayVo.getMembersNum();
        userProfileDisplayVo.setUsersNum(usersNum);
        userProfileDisplayVo.setMembersNum(membersNum);
        double ratio = membersNum / (usersNum * 1.0);
        userProfileDisplayVo.setMembershipRatio(String.format("%.2f",ratio));
        return userProfileDisplayVo;
    }

    private List<UserProfileDisplay> wrapToUserProfileDisplay(List<AppUserDetail> appUserDetails) {
        List<UserProfileDisplay> userProfileDisplays = new ArrayList<>();
        if (CollectionUtils.isEmpty(appUserDetails)) {
            return userProfileDisplays;
        }
        Map<Integer, List<AppUserDetail>> appUserDetailMap = appUserDetails.stream().peek(x -> {
            if (x.getProvinceCode() == null || x.getProvinceCode() == 0) {
                x.setProvinceCode(GUANG_DONG_CODE);
            }
        }).collect(Collectors.groupingBy(AppUserDetail::getProvinceCode, Collectors.toList()));

        UserProfileDisplay userProfileDisplay;
        Set<Map.Entry<Integer, List<AppUserDetail>>> appUserDetailEntrySet = appUserDetailMap.entrySet();
        for (Map.Entry<Integer, List<AppUserDetail>> appUserMapEntry : appUserDetailEntrySet) {
            userProfileDisplay = new UserProfileDisplay();
            Integer provinceCode = appUserMapEntry.getKey();
            userProfileDisplay.setProvinceCode(provinceCode);
            List<AppUserDetail> appUserDetailList = appUserMapEntry.getValue();
            userProfileDisplay.setUsersNum(appUserDetailList.size());
            long members = appUserDetailList.stream().filter(x -> Objects.equals(x.getIsMember(), 1)).count();
            userProfileDisplay.setMemberNums(members);
            userProfileDisplays.add(userProfileDisplay);
        }
        return userProfileDisplays;
    }
}
