package com.xxfc.platform.activity.biz;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.admin.dto.UserInfoDTO;
import com.github.wxiaoqi.security.admin.entity.AppUserLogin;
import com.github.wxiaoqi.security.admin.feign.UserFeign;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.github.wxiaoqi.security.common.util.process.SystemConfig;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import com.xxfc.platform.activity.constant.CouponUsed;
import com.xxfc.platform.activity.dto.UserCouponDTO;
import com.xxfc.platform.activity.dto.UserCouponFindDTO;
import com.xxfc.platform.activity.dto.UserCouponSendDTO;
import com.xxfc.platform.activity.entity.Coupon;
import com.xxfc.platform.activity.entity.IntegralUserTotal;
import com.xxfc.platform.activity.entity.UserCoupon;
import com.xxfc.platform.activity.feign.ActivityFeign;
import com.xxfc.platform.activity.vo.CouponVo;
import com.xxfc.platform.activity.vo.UserCouponPageVo;
import com.xxfc.platform.activity.vo.UserCouponVo;
import com.xxfc.platform.universal.weixin.util.Snowflake;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Arrays;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xxfc.platform.activity.mapper.UserCouponMapper;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 我的优惠卷
 *
 * @author libin
 * @email 18178966185@163.com
 * @date 2019-06-21 14:34:49
 */
@Service
@Slf4j
public class UserCouponBiz extends BaseBiz<UserCouponMapper, UserCoupon> {


    @Autowired
    private  CouponBiz couponBiz;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private  IntegralUserTotalBiz integralUserTotalBiz;

    private  static  final  Long  DAY=86400000L;

    //自动发送优惠卷
    public String authledCoupon(Integer userId){
        if (userId==null||userId==0){
            log.error("----参数不能为空");
            return  null;
        }
        Coupon coupon=couponBiz.getCouponByUsed(CouponUsed.ALLNEW.getCode());
        if (coupon==null){
            log.error(userId+"----无可领取优惠卷");
            return  null;
        }
        Integer couponId=coupon.getId();
        boolean falg=checkUserLed(userId,couponId);
        if(falg){
            log.error(userId+"----已领优惠卷");
            return  null;
        }
        return  led(coupon,userId);
    }

    //用户领劵
    public String userLedCoupon(Integer userId,Integer couponId){
        Coupon coupon=couponBiz.selectById(couponId);
        if (coupon==null||coupon.getIsDel()!=0||coupon.getStatus()!=1){
            log.error(userId+"----无可领取优惠卷");
            return null;
        }
        boolean falg=checkUserLed(userId,couponId);
        if(falg){
            log.error(userId+"----已领优惠卷");
            return null;
        }
        falg=checkLed(userId,couponId,coupon.getLimitCollar(),coupon.getQuota());
        if(falg){
            log.error(userId+"----已超过领取限制");
            return null;
        }
        return  led(coupon,userId);
    }

    //后台领劵(一个劵可以发多张)
    public String adminUserLedCoupon(Integer userId,Integer couponId){
        Coupon coupon=couponBiz.selectById(couponId);
        if (coupon==null||coupon.getIsDel()!=0||coupon.getStatus()!=1){
            log.error(userId+"----无可领取优惠卷");
            return null;
        }
        boolean falg=checkLed(userId,couponId,coupon.getLimitCollar(),coupon.getQuota());
        if(falg){
            log.error(userId+"----已超过领取限制");
            return null;
        }
        return  led(coupon,userId);
    }

    //领取动作
    public  String  led( Coupon coupon,Integer userId ){
        int type=coupon.getValidType();
        Integer couponId=coupon.getId();
        Long expireTime=System.currentTimeMillis();
        Long startTime=0L;
        if(type==1){
            startTime=coupon.getStartTime();
            expireTime=coupon.getValidEndTime();
        }else if (type==2){
            startTime=expireTime;
            expireTime+=DAY*coupon.getValidDays();
        } else {
            startTime=expireTime;
            expireTime=-1L;
        }
        String ticker_no=Snowflake.build()+"";
        UserCoupon userCoupon=new UserCoupon();
        userCoupon.setUserId(userId);
        userCoupon.setCouponId(couponId);
        userCoupon.setTickerNo(ticker_no);
        userCoupon.setStartTime(startTime);
        userCoupon.setExpireTime(expireTime);
        insertSelective(userCoupon);
        coupon.setTakeCount(coupon.getTakeCount()+1);
        couponBiz.updateSelectiveById(coupon);
        return  ticker_no;
    }

    //检查用户是否领卷
    public  boolean checkUserLed(Integer userId,Integer id){
        Example example=new Example(UserCoupon.class);
        example.createCriteria().andEqualTo("userId",userId).andEqualTo("couponId",id).andEqualTo("isDel",0);
        List<UserCoupon> list=selectByExample(example);
        if(list.size()>0){
            log.error(userId+"----已领优惠卷");
            return  true;
        }
        return false;
    }

    //检查用户是否可领卷
    public  boolean checkLed(Integer userId,Integer id,Integer limitCollar,Integer quota){
        Example example=new Example(UserCoupon.class);
        example.createCriteria().andEqualTo("userId",userId).andEqualTo("couponId",id).andEqualTo("isDel",0);
        Integer num=selectCountByExample(example);
        log.info("-用户已领劵--userId==="+userId+"----num==="+num+"----couponid==="+id);
        if(num==null||num==0){
            log.error(userId+"----无领此优惠卷----couponid==="+id);
            return  false;
        }
        if (limitCollar==null||num>=limitCollar){
            log.error(userId+"----此优惠卷超过每人限领次数----couponid==="+id+"----limitCollar==="+limitCollar);
            return  true;
        }
        example.clear();
        example.createCriteria().andEqualTo("couponId",id).andEqualTo("isDel",0);
        num=selectCountByExample(example);
        log.info("---发劵数量----num==="+num+"----limitCollar==="+limitCollar+"----quota==="+quota+"----couponid==="+id);
        if (quota==null||quota==0||(num!=null&&num>0&&num>=quota)){
            log.error(userId+"----此优惠卷超过发券数量----couponid==="+id+"----quota==="+quota);
            return  true;
        }
        return false;
    }

    //获取我的优惠卷
    public ObjectRestResponse getCouponList(Integer userId,int type,Integer channel,BigDecimal amout){
        if (userId==null||userId==0){
            log.error("----参数不能为空");
            return  ObjectRestResponse.createFailedResult(ResultCode.NULL_CODE,"参数不能为空");
        }
        if (amout.compareTo(BigDecimal.ZERO)<1){
            return  ObjectRestResponse.succ();
        }
        Long time=System.currentTimeMillis();
        List<UserCouponVo> list=mapper.getUserCouponsByType(userId,type,time,channel);
        List<UserCouponVo> list1=new ArrayList<>();
        List<UserCouponVo> list2=new ArrayList<>();
        if(list.size()>0){
            for (UserCouponVo couponVo:list){
                    Integer status=2;
                    if (amout.compareTo(new BigDecimal("0.00"))>0){
                        if(couponVo.getType()==1){
                            if (amout.compareTo(couponVo.getWithAmount())>=0){
                                status=1;
                            }
                            couponVo.setStatus(status);
                            list1.add(couponVo);
                        }else if (couponVo.getType()==3){
                            status=1;
                            couponVo.setStatus(status);
                            list2.add(couponVo);
                        }
                    }
            }
           // list.sort(Comparator.comparing(UserCouponVo::getStatus));
        }
        UserCouponVo userCouponVo=null;
        if (list2.size()>0){
            list2.sort(Comparator.comparing(UserCouponVo::getStatus));
             userCouponVo=list2.get(0);
                if (userCouponVo!=null){
                    userCouponVo.setIsChecked(1);
                    list2.set(0,userCouponVo);
                }

        }
        if (list1.size()>0){
            list1.sort(Comparator.comparing(UserCouponVo::getStatus));
            if (userCouponVo==null){
                int num=0;
                for (UserCouponVo couponVo:list1) {
                    if (couponVo.getStatus()==1){
                        userCouponVo=couponVo;
                        break;
                    }
                    num++;
                }
                if (userCouponVo!=null){
                    userCouponVo.setIsChecked(1);
                    list1.set(num,userCouponVo);
                }
            }

        }
        JSONArray array = new JSONArray();
        JSONObject object=new JSONObject();
        object.put("type",1);
        object.put("list",list1);
        array.add(object);
        JSONObject object1=new JSONObject();
        object1.put("type",3);
        object1.put("list",list2);
        array.add(object1);
        JSONObject result=new JSONObject();
        result.put("coupon",userCouponVo);
        result.put("array",array);
        return  ObjectRestResponse.succ(result);
    }
    //获取我的优惠卷
    public ObjectRestResponse getUserCouponList(Integer userId,int type,Integer channel,BigDecimal amout) {
        if (userId == null || userId == 0) {
            log.error("----参数不能为空");
            return ObjectRestResponse.createFailedResult(ResultCode.NULL_CODE, "参数不能为空");
        }
        Long time = System.currentTimeMillis();
        List<UserCouponVo> list = mapper.getUserCouponsByType(userId, type, time, channel);
        if (list.size() > 0) {
            for (UserCouponVo couponVo : list) {
                Integer status = 2;
                if (amout.compareTo(new BigDecimal("0.00")) > 0) {
                    if (couponVo.getType() == 1) {
                        if (amout.compareTo(couponVo.getWithAmount()) >= 0) {
                            status = 1;
                        }
                    } else if (couponVo.getType() == 3) {
                        status = 1;
                    }
                }
                couponVo.setStatus(status);
            }
            list.sort(Comparator.comparing(UserCouponVo::getStatus));
        }

        return ObjectRestResponse.succ(list);
    }


    //获取单个优惠卷
    public UserCouponVo getUserCoupon(String tickerNo){
        if (StringUtils.isBlank(tickerNo)){
            log.error("----参数不能为空");
            return  null;
        }
        return  mapper.getUserCoupon(tickerNo);
    }

    //支付后更新优惠卷状态:type.1-触发使用优惠券；0-不触发优惠券使用（在优惠券未使用时）；2--不触发优惠券使用（不管优惠券是否已使用）
    public BigDecimal useTickerNo(Integer userId, List<String> tickerNos, String orderNo,Integer channel,BigDecimal amout,Integer type){
        BigDecimal couponAmout=new BigDecimal("0.00");
        if(couponAmout.compareTo(amout) >= 0) {
            return BigDecimal.ZERO;
        }
        if (userId==null||userId==0||tickerNos==null||tickerNos.size()==0){
            log.error("----参数不能为空");
            return couponAmout;
        }
        Example example=new Example(UserCoupon.class);
        example.createCriteria().andIn("tickerNo", tickerNos).andEqualTo("isDel",0);
        List<UserCoupon> list=selectByExample(example);
        if(list.size()==0){
            log.error(userId+"----没有可用优惠卷--");
            return couponAmout;
        }
        for (UserCoupon userCoupon:list) {
            //zjw_0907 当type 为 check（即2）不判断 优惠券是否已使用
            if(userCoupon!=null && userCoupon.getIsUse()==1 && !ActivityFeign.TYPE_CHECK.equals(type)){
                log.error(userId+"----该优惠卷已使用--tickerNo==");
                continue;
            }
            Integer couponId=userCoupon.getCouponId();
            if (type==1){
                userCoupon.setIsUse(1);
                userCoupon.setOrderNo(orderNo);
                userCoupon.setUseTime(System.currentTimeMillis());
                updateSelectiveById(userCoupon);
                mapper.upUsedCount(couponId,1);

            }
            couponAmout=couponAmout.add(getCouponAmout(couponId,channel,amout));
        }
        if (couponAmout.compareTo(amout)>0){
            couponAmout=amout;
        }
        return couponAmout;
    }

    public  BigDecimal  getCouponAmout(Integer couponId,Integer channel,BigDecimal amout) {
        BigDecimal couponAmout = new BigDecimal("0.00");
        Coupon coupon = couponBiz.selectById(couponId);
        if (coupon != null && (coupon.getChannel() == channel||coupon.getChannel()==0)) {
            Integer type = coupon.getType();
            if (type != null) {
                BigDecimal useAmout = coupon.getUsedAmount();

                if (type == 3 || (type == 1 && (amout.compareTo(coupon.getWithAmount()) >= 0))) {
                    //couponAmout = amout.subtract(useAmout);
                    if (amout.compareTo(useAmout) > 0) {
                         couponAmout= useAmout;
                    }else {
                         couponAmout= amout;
                    }
                }
            }
        }
        return couponAmout;
    }

    //取消使用优惠卷
    public void cancelTickerNo(String TickerNo){
        if (StringUtils.isBlank(TickerNo)){
            log.error("----参数不能为空");
            return;
        }
        TickerNo=TickerNo.trim();
        Example example=new Example(UserCoupon.class);
        example.createCriteria().andEqualTo("tickerNo",TickerNo).andEqualTo("isDel",0);
        List<UserCoupon> list=selectByExample(example);
        if(list.size()==0){
            log.error(TickerNo+"----优惠卷不存在");
            return;
        }
        UserCoupon userCoupon=list.get(0);
       if (userCoupon!=null&&userCoupon.getIsUse()!=1){
           log.error(TickerNo+"----没有领优惠卷");
           return;
       }
        userCoupon.setIsUse(0);
        userCoupon.setOrderNo("");
        userCoupon.setUseTime(0L);
        updateSelectiveById(userCoupon);
        mapper.upUsedCount(userCoupon.getCouponId(),-1);
    }


    public PageDataVO<UserCouponPageVo> listUserCouponWithPage(UserCouponFindDTO userCouponFindDTO) {

        PageDataVO<UserCouponPageVo> userCouponPag = new PageDataVO<>();

        if (StringUtils.isNotEmpty(userCouponFindDTO.getPhone())) {
            AppUserLogin appUserLogin = userFeign.one(userCouponFindDTO.getPhone());
            userCouponFindDTO.setUserId(appUserLogin.getId());
        }
        PageDataVO<UserCouponDTO> pageDataVO = PageDataVO.pageInfo(userCouponFindDTO.getPage(), userCouponFindDTO.getLimit(), () -> mapper.findUserCoupons(userCouponFindDTO));
        List<UserCouponDTO> data = pageDataVO.getData();
        if (CollectionUtils.isEmpty(data)) {
            return userCouponPag;
        }
        Map<Integer, AppUserLogin> userIdAndAppuserLoginMap = new HashMap<>();

        if (StringUtils.isEmpty(userCouponFindDTO.getPhone())) {
            List<Integer> userIds = data.stream().map(UserCouponDTO::getUserId).distinct().collect(Collectors.toList());
            userIdAndAppuserLoginMap = userFeign.findAppUsersByUserIds(userIds);
        }
        List<UserCouponPageVo> userCouponPageVos = new ArrayList<>();
        UserCouponPageVo userCouponPageVo;
        for (UserCouponDTO userCouponDTO : data) {
            userCouponPageVo = new UserCouponPageVo();
            BeanUtils.copyProperties(userCouponDTO, userCouponPageVo);
            if (StringUtils.isNotEmpty(userCouponFindDTO.getPhone())) {
                userCouponPageVo.setPhone(userCouponFindDTO.getPhone());
            } else {
                userCouponPageVo.setPhone(userIdAndAppuserLoginMap.get(userCouponDTO.getUserId()) == null ? "" : userIdAndAppuserLoginMap.get(userCouponDTO.getUserId()).getUsername());
            }
            userCouponPageVos.add(userCouponPageVo);
        }

        userCouponPag.setPageSize(pageDataVO.getPageSize());
        userCouponPag.setPageNum(pageDataVO.getPageNum());
        userCouponPag.setTotalCount(pageDataVO.getTotalCount());
        userCouponPag.setTotalPage(pageDataVO.getTotalPage());
        userCouponPag.setData(userCouponPageVos);
        return userCouponPag;
    }

    public int sendCoupon(UserCouponSendDTO userCouponSendDTO) {
        AppUserLogin appUserLogin = userFeign.one(userCouponSendDTO.getPhone());
        CouponVo couponVo = couponBiz.findCouponById(userCouponSendDTO.getCouponId());
        UserCoupon userCoupon;
        List<UserCoupon> userCoupons = new ArrayList<>();
        for (int i=0;i<userCouponSendDTO.getCouponNum();i++){
            /*userCoupon = new UserCoupon();
            userCoupon.setCouponId(userCouponSendDTO.getCouponId());
            userCoupon.setUserId(appUserLogin.getId());
            userCoupon.setCrtTime(Instant.now().toEpochMilli());
            userCoupon.setStartTime(couponVo.getValidStartTime());
            userCoupon.setExpireTime(couponVo.getValidEndTime());
            userCoupon.setTickerNo(Snowflake.build()+"");
            userCoupons.add(userCoupon);*/
            adminUserLedCoupon(appUserLogin.getId(),userCouponSendDTO.getCouponId());
        }
        return 1;
    }

    public long importUserCoupon(Integer couponId,List<String[]> userCounponData) {

        List<String> phones = userCounponData.stream().map(x -> x[0]).collect(Collectors.toList());
        Map<String,Integer> phoneAndAppUserLoginMap = userFeign.findAppusersByUserNames(phones);
        CouponVo couponVo = couponBiz.findCouponById(couponId);
        UserCoupon userCoupon;
        List<UserCoupon> userCoupons = new ArrayList<>();
        long length = userCounponData.size();
        for (int i=0;i<length;i++){
            userCoupon = new UserCoupon();
            userCoupon.setCouponId(couponId);
            userCoupon.setStartTime(couponVo.getValidStartTime());
            userCoupon.setExpireTime(couponVo.getValidEndTime());
            userCoupon.setCrtTime(Instant.now().toEpochMilli());
            userCoupon.setUserId(phoneAndAppUserLoginMap.get(userCounponData.get(i)[0]));
            userCoupon.setTickerNo(Snowflake.build()+"");
            userCoupons.add(userCoupon);
        }

        return mapper.inserBatch(userCoupons);
    }


    public UserInfoDTO getUserInfo(Integer userId)throws  Exception{
        UserInfoDTO  userInfoDTO=new UserInfoDTO();
        IntegralUserTotal integralUserTotal=new  IntegralUserTotal();
        integralUserTotal.setUserId(userId);
        integralUserTotal=integralUserTotalBiz.selectOne(integralUserTotal);
        if (integralUserTotal!=null){
            BeanUtils.copyProperties(integralUserTotal,userInfoDTO);
        }else {
            userInfoDTO.setTotalPoint(0);
        }
        List<UserCouponVo> coupons = mapper.getUserCouponsByType(userId, 0, System.currentTimeMillis(), null);
        Long couponNumber = 0L;
        if (coupons.size() > 0){
            couponNumber=Long.parseLong(coupons.size()+"");
        }
        userInfoDTO.setCouponNumber(couponNumber);
        return  userInfoDTO;
    }

    public void deleteByUserIds(List<Integer> userIds) {
        Example example = new Example(UserCoupon.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("userId",userIds);
        mapper.deleteByExample(example);
    }

    public void updateUserCouponStatusById(Integer id) {
        mapper.updateUserCouponStatusById(id);
    }
}