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

import com.ace.cache.annotation.Cache;
import com.ace.cache.annotation.CacheClear;
import com.github.wxiaoqi.security.admin.dto.BaseUserMemberVO;
import com.github.wxiaoqi.security.admin.dto.UserMemberDTO;
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.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.exception.BaseException;
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 com.github.wxiaoqi.security.admin.entity.BaseUserMember;
import com.github.wxiaoqi.security.admin.mapper.BaseUserMemberMapper;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
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.lang.reflect.InvocationTargetException;

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
    private BaseUserMemberExportBiz baseUserMemberExportBiz;

    @Autowired
    private HttpServletRequest request;
//    @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);

            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("保存成功");

    }


    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));
        executorService.submit(()->{
            try {
                AppUserVo qppUser = detailBiz.getUserInfoById(beforeMember.getUserId());
                BaseUserMemberExport baseUserMemberExport = BaseUserMemberExport
                        .builder()
                        .username(qppUser.getUsername())
                        .beforeMemberLevel(beforeMember.getMemberLevel())
                        .memberLevel(aftereMember.getMemberLevel())
                        .totalNumber(aftereMember.getTotalNumber() - beforeMember.getTotalNumber())
                        .rentFreeDays(aftereMember.getRentFreeDays() - beforeMember.getRentFreeDays())
                        .beforeDiscount(beforeMember.getDiscount())
                        .discount(aftereMember.getDiscount())
                        .status(1)
                        .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("保存修改会员记录成功");
        });
    }
}