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

import com.ace.cache.annotation.Cache;
import com.ace.cache.annotation.CacheClear;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.admin.dto.BaseUserMemberVO;
import com.github.wxiaoqi.security.admin.dto.UserMemberDTO;
import com.github.wxiaoqi.security.admin.entity.AppUserRelation;
import com.github.wxiaoqi.security.admin.entity.BaseUserMember;
import com.github.wxiaoqi.security.admin.entity.BaseUserMemberExport;
import com.github.wxiaoqi.security.admin.entity.BaseUserMemberLevel;
import com.github.wxiaoqi.security.admin.mapper.BaseUserMemberLevelMapper;
import com.github.wxiaoqi.security.admin.mapper.BaseUserMemberMapper;
import com.github.wxiaoqi.security.admin.vo.AppUserVo;
import com.github.wxiaoqi.security.admin.vo.UserMemberVo;
import com.github.wxiaoqi.security.auth.client.config.UserAuthConfig;
import com.github.wxiaoqi.security.auth.client.jwt.UserAuthUtil;
import com.github.wxiaoqi.security.auth.common.util.jwt.IJWTInfo;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.config.rabbit.RabbitConstant;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.xxfc.platform.universal.feign.MQSenderFeign;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 用户会员表
 *
 * @author zjw
 * @email nishijjo@qq.com
 * @date 2019-06-18 19:38:56
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class BaseUserMemberBiz extends BaseBiz<BaseUserMemberMapper, BaseUserMember> {

    @Autowired
    private AppUserDetailBiz detailBiz;

    @Autowired
    private BaseUserMemberLevelMapper BaseUserMemberLevelMapper;

    private  ExecutorService executorService = Executors.newCachedThreadPool();

    @Autowired
    private UserAuthUtil userAuthUtil;

    @Autowired
    private UserAuthConfig userAuthConfig;

    @Autowired
    AppUserRelationBiz appUserRelationBiz;

    @Autowired
    private BaseUserMemberExportBiz baseUserMemberExportBiz;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    MQSenderFeign mqSenderFeign;

//    @Autowired
//    private TaskExecutor taskExecutor;
//
//    @Autowired
//    private UserMemberLevelBiz userMemberLevelBiz;
//
//    @Autowired
//    private AppUserLoginBiz appUserLoginBiz;

    //获取用户会员信息
    @Cache(key = "user:member{1}")
    public UserMemberVo getMemberInfoByUserId(Integer userId) {
        return mapper.getInfoByUserId(userId);
}

    //更新会员信息
    @Override
    @CacheClear(key = "user:member{1.userId}")
    public void updateSelectiveById(BaseUserMember userMember) {
        super.updateSelectiveById(userMember);
    }


    //用户购买会员信息更新
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updUserMemberByUserId(UserMemberDTO userMemberDTO) throws Exception {
        if (userMemberDTO == null) {
            log.error("updUserMemberByUserId----参数为空");
            return;
        }
        Integer userId = userMemberDTO.getUserId();

        UserMemberVo userMemberVo = getMemberInfoByUserId(userId);

        BaseUserMember baseUserMember = new BaseUserMember();
        BeanUtils.copyProperties(baseUserMember, userMemberDTO);
        Integer freeDays = baseUserMember.getRentFreeDays();
        Integer totalNumber = baseUserMember.getTotalNumber() == null ? 0 : baseUserMember.getTotalNumber();
        if (freeDays == null || freeDays == 0) {
            freeDays = totalNumber;
        }
        Integer buyCount = 1;
        if (userMemberDTO.getBuyCount() != null) {
            buyCount = userMemberDTO.getBuyCount();
        }
        if (userMemberVo == null) {
            baseUserMember.setRentFreeDays(freeDays);
            baseUserMember.setBuyCount(buyCount);
            insertSelective(baseUserMember);
        } else {
            Integer discount = userMemberVo.getDiscount() == null ? 0 : userMemberVo.getDiscount();
            Integer discount1 = baseUserMember.getDiscount() == null ? 0 : baseUserMember.getDiscount();
            if (discount < discount1) {
                baseUserMember.setDiscount(discount);
            }
            Integer level = userMemberVo.getMemberLevel() == null ? 0 : userMemberVo.getMemberLevel();
            Integer level1 = baseUserMember.getMemberLevel() == null ? 0 : baseUserMember.getMemberLevel();
            if (level > level1) {
                baseUserMember.setMemberLevel(level);
            }
            baseUserMember.setId(userMemberVo.getId());
            totalNumber += userMemberVo.getTotalNumber() == null ? 0 : userMemberVo.getTotalNumber();
            freeDays += userMemberVo.getRentFreeDays() == null ? 0 : userMemberVo.getRentFreeDays();
            baseUserMember.setBuyCount(userMemberVo.getBuyCount() + buyCount);
            baseUserMember.setTotalNumber(totalNumber);
            baseUserMember.setRentFreeDays(freeDays);
            baseUserMember.setMemberType(2);
            getMyBiz().updateSelectiveById(baseUserMember);
        }
        AppUserVo userVo = detailBiz.getUserInfoById(userId);
        if (userVo != null && (userVo.getIsMember() == null || userVo.getIsMember() == 0)) {
            AppUserVo userVo1 = new AppUserVo();
            userVo1.setId(userVo.getId());
            userVo1.setUserid(userId);
            userVo1.setIsMember(1);
            detailBiz.updUuserInfoById(userVo1);
        }

    }


    /**
     * //
     *
     * @param userId
     * @param days
     * @param type;1-用户锁定下单；2-购买下单;3-取消订单
     * @return
     */
    public int upMemberDays(Integer userId, Integer days, Integer type) {
        int num = -1;
        UserMemberVo userMemberVo = getMemberInfoByUserId(userId);
        if (userMemberVo != null) {
            days = days == null ? 0 : days;
            Integer freeDays = userMemberVo.getRentFreeDays() == null ? 0 : userMemberVo.getRentFreeDays();
            // Integer lockDays=userMemberVo.getLockDays()==null?userMemberVo.getLockDays():0;
            Integer totalNumber = userMemberVo.getTotalNumber() == null ? 0 : userMemberVo.getTotalNumber();
            BaseUserMember baseUserMember = new BaseUserMember();
            baseUserMember.setId(userMemberVo.getId());
            baseUserMember.setUserId(userId);
            if (type == 1) {
                /*if((freeDays-lockDays)>0&&(freeDays-lockDays)>=days){
                    baseUserMember.setLockDays(lockDays+days);
                    updateSelectiveById(baseUserMember);
                    num=freeDays-(lockDays+days);
                }*/
                if (freeDays > 0 && freeDays >= days) {
                    freeDays = freeDays - days;
                    baseUserMember.setRentFreeDays(freeDays);
                }
                Integer payCount = userMemberVo.getPayCount() == null ? 0 : userMemberVo.getPayCount();
                   /* if (days > 0) {
                        payCount = payCount + 1;
                    }*/
                baseUserMember.setPayCount(payCount);
                getMyBiz().updateSelectiveById(baseUserMember);
                num = freeDays;
            } else if (type == 2) {
                    /*Integer payCount=userMemberVo.getPayCount()==null?0:userMemberVo.getPayCount();
                    payCount=payCount+1;
                    freeDays=(freeDays-days)>0?(freeDays-days):0;
                    lockDays=lockDays>0?(lockDays-days)>0?(lockDays-days):0:0;
                    baseUserMember.setRentFreeDays(freeDays);
                    baseUserMember.setPayCount(payCount);
                    baseUserMember.setLockDays(lockDays);
                    updateSelectiveById(baseUserMember);
                    num=freeDays-lockDays;*/
                /*Integer payCount=userMemberVo.getPayCount()==null?0:userMemberVo.getPayCount();
                if(days>0){
                    payCount=payCount+1;
                }
                baseUserMember.setPayCount(payCount);
                getMyBiz().updateSelectiveById(baseUserMember);*/
                num = freeDays;
            } else {
                /*lockDays=lockDays>0?(lockDays-days)>0?(lockDays-days):0:0;
                baseUserMember.setLockDays(lockDays);
                getMyBiz().updateSelectiveById(baseUserMember);
                num=freeDays-lockDays;*/
                freeDays = (freeDays + days) > 0 ? (freeDays + days) : 0;
                freeDays = freeDays > totalNumber ? totalNumber : freeDays;
                baseUserMember.setRentFreeDays(freeDays);
                getMyBiz().updateSelectiveById(baseUserMember);
                num = freeDays;
            }

        }
        return num;
    }

    private BaseUserMemberBiz getMyBiz() {
        return AopContext.currentProxy() != null ? (BaseUserMemberBiz) AopContext.currentProxy() : this;
    }

    /**
     * 获取用户会员信息
     *
     * @param userId
     * @return
     */
    public BaseUserMemberVO findOneByUserId(Integer userId) {

        BaseUserMemberVO baseUserMemberVO = mapper.getBaseUserMemberVOByUserId(userId);
        if (baseUserMemberVO != null) {
            return baseUserMemberVO;
        }
        return null;

    }


    /**
     * 设置用户会员
     *
     * @param userMemberDTO
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void UpdateUserMember(UserMemberDTO userMemberDTO) throws Exception {

        Integer userId = userMemberDTO.getUserId();
        BaseUserMember baseUserMember = new BaseUserMember();
        BeanUtils.copyProperties(baseUserMember, userMemberDTO);
        Integer freeDays = baseUserMember.getRentFreeDays() == null ? 0 : baseUserMember.getRentFreeDays();
        Integer totalNumber = baseUserMember.getTotalNumber() == null ? 0 : baseUserMember.getTotalNumber();
        if (totalNumber < freeDays) {
            freeDays = totalNumber;
        }
        if (userMemberDTO.getMemberLevel() != null) {
            Example exa = new Example(BaseUserMemberLevel.class);
            Example.Criteria criteria = exa.createCriteria();
            criteria.andEqualTo("isdel", 0);
            criteria.andEqualTo("level",userMemberDTO.getMemberLevel());
            List<BaseUserMemberLevel> levels = BaseUserMemberLevelMapper.selectByExample(exa);
            if (CollectionUtils.isEmpty(levels)) {
                log.error("错误!设置的该等级会员不存在.");
                throw new BaseException("错误!设置的该等级会员不存在。");
            }else if (levels.size()>1){
                log.error("错误!该等级的会员存在多个。");
                throw new BaseException("错误!该等级的会员存在多个。");
            }else {
                baseUserMember.setDiscount(levels.get(0).getDiscount());
            }
        }

        Integer buyCount = userMemberDTO.getBuyCount() == null ? 1 : userMemberDTO.getBuyCount();
        UserMemberVo userMemberVo = getMemberInfoByUserId(userMemberDTO.getUserId());
        //保存修改记录
        if (userMemberVo == null) {
            baseUserMember.setRentFreeDays(freeDays);
            baseUserMember.setBuyCount(buyCount);
            insertSelective(baseUserMember);
        } else {
            baseUserMember.setId(userMemberVo.getId());
            Integer number = userMemberVo.getTotalNumber() == null ? 0 : userMemberVo.getTotalNumber();
            Integer days = userMemberVo.getRentFreeDays() == null ? 0 : userMemberVo.getRentFreeDays();
            baseUserMember.setBuyCount(userMemberVo.getBuyCount() + buyCount);
            number = (totalNumber - number) + number;
            days = (freeDays - days) + days;
            baseUserMember.setTotalNumber(number);
            baseUserMember.setRentFreeDays(days);
            getMyBiz().updateSelectiveById(baseUserMember);
        }
        AppUserVo userVo = detailBiz.getUserInfoById(userId);
        if (userVo != null && (userVo.getIsMember() == null || userVo.getIsMember() == 0)) {
            AppUserVo userVo1 = new AppUserVo();
            userVo1.setId(userVo.getId());
            userVo1.setUserid(userId);
            userVo1.setIsMember(1);
            detailBiz.updUuserInfoById(userVo1);
        }
        log.info("保存修改记录");
        setModifyData(userMemberVo,baseUserMember);
        log.info("保存成功");

    }

    /**
     * 修改用户会员等级
     * @param baseUserMember
     * @return
     */
    public ObjectRestResponse updateUserLevel(BaseUserMember baseUserMember) {
        if (baseUserMember.getId() == null || baseUserMember.getMemberLevel() == null) {
            return ObjectRestResponse.paramIsEmpty();
        }
        BaseUserMember old = selectById(baseUserMember.getId());
        if (old == null) {
            return ObjectRestResponse.createFailedResult(ResultCode.NOTEXIST_CODE, ResultCode.getMsg(ResultCode.NOTEXIST_CODE));
        }
        baseUserMember.setMemberLevel(baseUserMember.getMemberLevel());
        updateSelectiveByIdRe(baseUserMember);
        // todo 执行上级会员等级初始化操作
        mqSenderFeign.sendMessage(RabbitConstant.ADMIN_TOPIC, RabbitConstant.KEY_MEMBER_CHANGE, JSONObject.toJSONString(baseUserMember));
        return ObjectRestResponse.succ();
    }

    //处理上级会员等级初始化
    public void executeParentMemberLevel(BaseUserMember baseUserMember) {
            log.info("【处理上级会员等级】： {}", baseUserMember);
            Example example = new Example(BaseUserMemberLevel.class);
            example.createCriteria().andEqualTo("isdel", 0);
            example.orderBy("level");
            List<BaseUserMemberLevel> userMemberLevelList = BaseUserMemberLevelMapper.selectByExample(example);
            if (userMemberLevelList != null && userMemberLevelList.size() > 0) {
                generateParentLevel(baseUserMember.getUserId(), userMemberLevelList);
            }
    }
    private void generateParentLevel(Integer userId, List<BaseUserMemberLevel> userMemberLevelList) {
        AppUserRelation appUserRelation = appUserRelationBiz.getRelationByUserId(userId);
        if (appUserRelation != null && appUserRelation.getIsDel() != 1) {
            //查询上级当前等级
            Integer parentId = appUserRelation.getParentId();
            BaseUserMemberVO parentUser = findOneByUserId(parentId);
            log.info("【上级会员信息】: {}", parentUser);
            if (parentUser != null && parentId != 0) {
                //查询当前会员需要变更到的级别
                Integer parentNewLevel = generateUserLevel(parentId, parentUser.getMemberLevel(), userMemberLevelList);
                //如果返回为空，或者当前级别和需要更新的级别相等，不做处理
                log.info("【上级需要修改等级为: {}】", parentNewLevel);
                if (parentNewLevel != null && !parentNewLevel.equals(parentUser.getMemberLevel())) {
                    Example example1 = new Example(BaseUserMember.class);
                    example1.createCriteria().andEqualTo("userId", parentId).andEqualTo("isDel", 0);
                    BaseUserMember parent = mapper.selectOneByExample(example1);
                    if (parent != null) {
                        parent.setMemberLevel(parentNewLevel);
                        updateSelectiveByIdRe(parent);
                    }
                    generateParentLevel(parentId, userMemberLevelList);
                }
            }
        }
    }


    /**
     * 获取用户需要修改的等级
     * @param userId
     * @param level
     * @param userMemberLevelList
     */
    private Integer generateUserLevel(Integer userId, Integer level, List<BaseUserMemberLevel> userMemberLevelList) {
        BaseUserMemberLevel currentLevel = null;
        BaseUserMemberLevel subLevel = null;
        for (int i = 0; i < userMemberLevelList.size(); i ++ ) {
            if (level.equals(userMemberLevelList.get(i).getLevel())) {
                currentLevel = userMemberLevelList.get(i);
                if ((i+1) < userMemberLevelList.size()) {
                    subLevel = userMemberLevelList.get(i + 1);
                }
            }
        }
        //当前会员不存在，直接返回
        if (currentLevel == null) {
            return null;
        }
        //当前会员不分成且下一级也是不分成，直接返回
        if ( currentLevel.getIsShare() != null && currentLevel.getIsShare() == 0 ) {
            //下一级不存在、或者下一级不分成，就直接返回
            if (subLevel == null || (subLevel != null && subLevel.getIsShare() != null && subLevel.getIsShare() == 0)) {
                return currentLevel.getLevel();
            }
        }
        Example example = new Example(BaseUserMemberLevel.class);
        example.createCriteria().andEqualTo("isdel", 0).andEqualTo("isShare", 1);
        example.orderBy("level");
        List<BaseUserMemberLevel> baseUserMemberLevelList = BaseUserMemberLevelMapper.selectByExample(example);
        //如果当前等级小于等于第一个分成等级的低一等级, 则直接查询大于等于第一个分成等级的低一等级的下级用户数量， 否则直接取当前等级的低一级会员数量
        Integer queryLevel = level - 1;
        if (level <= (baseUserMemberLevelList.get(0).getLevel() - 1)) {
            queryLevel = baseUserMemberLevelList.get(0).getLevel() - 1;
        }
        //需要分成，则查询当前用户的下级是否符合条件，符合条件level+1
        List<BaseUserMember> baseUserMemberList = mapper.selectAllChildrenByLevel(userId, queryLevel);
        if (baseUserMemberList != null && baseUserMemberList.size() > getLimitNumber()) {
            return generateUserLevel(userId, level+1, userMemberLevelList);
        } else {
            return level;
        }
    }

    private Integer getLimitNumber() {
        return 3;
    }


    public void deleteByUserIds(Collection<Integer> userIds) {
        Example example = new Example(BaseUserMember.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("userId", userIds);
        mapper.deleteByExample(example);
    }
    private void setModifyData(UserMemberVo beforeMember, BaseUserMember aftereMember) throws Exception {

        log.info("保存修改会员记录={}",aftereMember);
        IJWTInfo infoFromToken = userAuthUtil.getInfoFromToken(userAuthConfig.getToken(request));
        log.info("token信息={}",infoFromToken);
        if (beforeMember==null) {
             beforeMember = new UserMemberVo();
        }
        UserMemberVo finalBeforeMember = beforeMember;
        executorService.submit(()->{
            try {
                AppUserVo qppUser = detailBiz.getUserInfoById(aftereMember.getUserId());
                BaseUserMemberExport baseUserMemberExport = BaseUserMemberExport
                        .builder()
                        .username(qppUser.getUsername())
                        .beforeMemberLevel(finalBeforeMember.getMemberLevel())
                        .memberLevel(aftereMember.getMemberLevel())
                        .totalNumber(aftereMember.getTotalNumber() - (finalBeforeMember.getTotalNumber()==null?0:finalBeforeMember.getTotalNumber()))
                        .rentFreeDays(aftereMember.getRentFreeDays() - (finalBeforeMember.getRentFreeDays()==null?0:finalBeforeMember.getRentFreeDays()))
                        .beforeDiscount(finalBeforeMember.getDiscount())
                        .discount(aftereMember.getDiscount())
                        .status(1)
                        .userId(aftereMember.getUserId())
                        .crtTime(System.currentTimeMillis())
                        .crtId(Integer.valueOf(infoFromToken.getId()))
                        .crtName(infoFromToken.getUniqueName())
                        .memberName(qppUser.getRealname())
                        .source(1)
                        .build();
                baseUserMemberExportBiz.insertSelective(baseUserMemberExport);

                System.out.println(baseUserMemberExport);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("保存修改会员记录失败"+e.getMessage());
            }
            log.info("保存修改会员记录成功");
        });
    }
}