package com.fs.store.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.fs.common.core.domain.R;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.IpUtil;
import com.fs.store.domain.FsStoreOrder;
import com.fs.store.domain.FsStoreOrderItem;
import com.fs.store.domain.FsUserBill;
import com.fs.store.dto.FsStoreCartDTO;
import com.fs.store.enums.BillDetailEnum;
import com.fs.store.mapper.FsStoreOrderMapper;
import com.fs.store.mapper.FsStoreProductAttrValueMapper;
import com.fs.store.mapper.FsUserTuiMoneyRankMapper;
import com.fs.store.param.LoginMpWxParam;
import com.fs.store.service.IFsUserBillService;
import com.fs.store.utils.JwtUtils;
import com.fs.store.vo.FsUserListVO;
import com.fs.store.vo.FsUserVO;
import com.fs.store.vo.FsCompanyUserListQueryVO;
import com.fs.store.vo.FsUserShareVO;
import com.fs.store.vo.FsUserTuiVO;
import com.fs.wx.miniapp.config.WxMaConfiguration;
import com.fs.wx.miniapp.config.WxMaProperties;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.fs.store.mapper.FsUserMapper;
import com.fs.store.domain.FsUser;
import com.fs.store.service.IFsUserService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;

import static com.fs.store.enums.BillDetailEnum.CATEGORY_1;
import static com.fs.store.enums.BillDetailEnum.CATEGORY_3;
import static com.fs.until.PhoneUtil.decryptPhone;
import static com.fs.until.PhoneUtil.encryptPhone;

/**
 * 用户Service业务层处理
 *
 * @author fs
 * @date 2022-03-15
 */
@Service
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
public class FsUserServiceImpl implements IFsUserService
{
    @Autowired
    private FsUserMapper fsUserMapper;

    @Autowired
    private FsStoreProductAttrValueMapper storeProductAttrValueMapper;

    @Autowired
    private IFsUserBillService billService;
    @Autowired
    private FsStoreOrderMapper storeOrderMapper;

    @Autowired
    private WxMaProperties maProperties;

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private JwtUtils jwtUtils;



    Logger logger =  LoggerFactory.getLogger(FsUserServiceImpl.class);


    /**
     * 查询用户
     *
     * @param userId 用户ID
     * @return 用户
     */
    @Override
    public FsUser selectFsUserById(Long userId)
    {
        return fsUserMapper.selectFsUserById(userId);
    }


    @Override
    public FsUserVO selectFsUserByUserId(Long userId) {
        return fsUserMapper.selectFsUserByUserId(userId);
    }

    /**
     * 查询用户列表
     *
     * @param fsUser 用户
     * @return 用户
     */
    @Override
    public List<FsUser> selectFsUserList(FsUser fsUser)
    {
        return fsUserMapper.selectFsUserList(fsUser);
    }


    @Override
    public List<FsUserListVO> selectFsUserVOList(FsUser fsUser) {
        return fsUserMapper.selectFsUserVOList(fsUser);
    }

    /**
     * 新增用户
     *
     * @param fsUser 用户
     * @return 结果
     */
    @Override
    public int insertFsUser(FsUser fsUser)
    {
        fsUser.setCreateTime(DateUtils.getNowDate());
        return fsUserMapper.insertFsUser(fsUser);
    }

    /**
     * 修改用户
     *
     * @param fsUser 用户
     * @return 结果
     */
    @Override
    public int updateFsUser(FsUser fsUser)
    {
        fsUser.setUpdateTime(DateUtils.getNowDate());
        return fsUserMapper.updateFsUser(fsUser);
    }

    /**
     * 批量删除用户
     *
     * @param userIds 需要删除的用户ID
     * @return 结果
     */
    @Override
    public int deleteFsUserByIds(Long[] userIds)
    {
        return fsUserMapper.deleteFsUserByIds(userIds);
    }

    /**
     * 删除用户信息
     *
     * @param userId 用户ID
     * @return 结果
     */
    @Override
    public int deleteFsUserById(Long userId)
    {
        return fsUserMapper.deleteFsUserById(userId);
    }

    @Override
    public int decIntegral(Long uid, double usedIntegral) {
        return fsUserMapper.decIntegral(uid,usedIntegral);
    }

    @Override
    public int incPayCount(Long userId) {
        return fsUserMapper.incPayCount(userId);
    }

    @Override
    public FsUser selectFsUserByPhone(String phone) {
        return fsUserMapper.selectFsUserByPhone(phone);
    }

    @Override
    public List<FsCompanyUserListQueryVO> selectFsCompanyUserListQuery(FsUser fsUser) {
        return fsUserMapper.selectFsCompanyUserListQuery(fsUser);
    }

    @Override
    public List<FsUserTuiVO> selectFsUserTuiList(String userId) {
        return fsUserMapper.selectFsUserTuiList(userId);
    }

    @Override
    public Long selectFsUserCount(int type,Long companyId) {
        return fsUserMapper.selectFsUserCount(type,companyId);
    }

    @Override
    @Transactional
    public void     addTuiMoney(FsStoreOrder order , List<FsStoreOrderItem> items) {
        //更新推荐人
//        FsUser user= fsUserMapper.selectFsUserById(order.getUserId());
//        if(user.getSpreadUserId()==null||user.getSpreadUserId()==0){
//            FsUser userMap=new FsUser();
//            userMap.setUserId(user.getUserId());
//            userMap.setSpreadUserId(order.getTuiUserId());
//            userMap.setIsPromoter(1);
//            fsUserMapper.updateFsUser(userMap);
//        }
        //获取一级二级佣金
        BigDecimal brokerage=BigDecimal.ZERO;
        BigDecimal brokerageTwo=BigDecimal.ZERO;
        BigDecimal brokerageThree=BigDecimal.ZERO;
        try {
            for(FsStoreOrderItem item: items){
                FsStoreCartDTO cartDTO= JSONUtil.toBean(item.getJsonInfo(),FsStoreCartDTO.class);
                if(cartDTO.getBrokerage()!=null){
                    brokerage=brokerage.add(cartDTO.getBrokerage().multiply(new BigDecimal(cartDTO.getNum().toString())));
                }
                if(cartDTO.getBrokerageTwo()!=null){
                    brokerageTwo=brokerageTwo.add(cartDTO.getBrokerageTwo().multiply(new BigDecimal(cartDTO.getNum().toString())));
                }
                if(cartDTO.getBrokerageThree()!=null){
                    brokerageThree= brokerageThree.add(cartDTO.getBrokerageThree().multiply(new BigDecimal(cartDTO.getNum().toString()))) ;
                }
            }
            //返佣金
            FsUser tuiUser=null;
            //如果推广员是自己，一级拿佣金
            FsUser user= fsUserMapper.selectFsUserById(order.getUserId());
            if(user.getIsPromoter().equals(1)){
                logger.info("拿一级佣金："+user.getUserId());
                tuiUser=user;
            }
            else{
                tuiUser= fsUserMapper.selectFsUserById(order.getTuiUserId());
                logger.info("else拿一级佣金："+tuiUser.getUserId());
            }
            //一级
            if(tuiUser!=null&&tuiUser.getIsPromoter()==1){
                if(brokerage.compareTo(BigDecimal.ZERO)==1){
                    FsUser tuiUserMap=new FsUser();
                    tuiUserMap.setUserId(tuiUser.getUserId());
                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().add(brokerage));
                    fsUserMapper.updateFsUser(tuiUserMap);
                    logger.info("拿一级佣金："+tuiUserMap.getUserId()+":"+brokerage);
                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerage.doubleValue(),tuiUserMap.getBrokeragePrice().doubleValue(),"订单返佣金",order.getId().toString(),order.getUserId());
                }
            }
            //二级返
            if(tuiUser!=null){
                FsUser tuiUserTwo= fsUserMapper.selectFsUserById(tuiUser.getSpreadUserId());
                if(tuiUserTwo!=null&&tuiUserTwo.getIsPromoter()==1){
                    if(brokerageTwo.compareTo(BigDecimal.ZERO)==1){
                        FsUser tuiUserTwoMap=new FsUser();
                        tuiUserTwoMap.setUserId(tuiUserTwo.getUserId());
                        tuiUserTwoMap.setBrokeragePrice(tuiUserTwo.getBrokeragePrice().add(brokerageTwo));
                        fsUserMapper.updateFsUser(tuiUserTwoMap);
                        logger.info("拿二级佣金："+tuiUserTwoMap.getUserId()+":"+brokerageTwo);
                        billService.addBill(tuiUserTwoMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerageTwo.doubleValue(),tuiUserTwoMap.getBrokeragePrice().doubleValue(),"订单返佣金",order.getId().toString(),tuiUser.getUserId());
                    }
                    //三级
                    FsUser tuiUserThree= fsUserMapper.selectFsUserById(tuiUserTwo.getSpreadUserId());
                    if(tuiUserThree!=null&&tuiUserThree.getIsPromoter()==1){
                        if(brokerageThree.compareTo(BigDecimal.ZERO)==1){
                            FsUser tuiUserThreeMap=new FsUser();
                            tuiUserThreeMap.setUserId(tuiUserThree.getUserId());
                            tuiUserThreeMap.setBrokeragePrice(tuiUserThree.getBrokeragePrice().add(brokerageThree));
                            fsUserMapper.updateFsUser(tuiUserThreeMap);
                            logger.info("拿三级佣金："+tuiUserThreeMap.getUserId()+":"+brokerageThree);
                            billService.addBill(tuiUserThreeMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerageThree.doubleValue(),tuiUserThreeMap.getBrokeragePrice().doubleValue(),"订单返佣金",order.getId().toString(),tuiUser.getUserId());
                        }

                    }
                }

            }


        }
        catch (Exception e){

        }
    }

    @Override
    @Transactional
    public void subTuiMoney(FsStoreOrder order) {
        FsUserBill map=new FsUserBill();
        map.setCategory(CATEGORY_3.getValue());
        map.setBusinessId(order.getId().toString());
        map.setBillType(1);
        List<FsUserBill> list=billService.selectFsUserBillList(map);
        if(list!=null&&list.size()>0){
            for(FsUserBill bill:list){
                FsUser tuiUser= fsUserMapper.selectFsUserByIdForUpdate(bill.getUserId());
                if(tuiUser!=null){
                    FsUser tuiUserMap=new FsUser();
                    tuiUserMap.setUserId(tuiUser.getUserId());
                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(new BigDecimal(bill.getNumber())));
                    fsUserMapper.updateFsUser(tuiUserMap);
                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),bill.getNumber().doubleValue(),tuiUserMap.getBrokeragePrice().doubleValue(),"订单退佣金",order.getId().toString(),bill.getTuiUserId());
                }
            }
        }

    }

    @Override
    @Transactional
    public void addMoney(FsStoreOrder order) {
        FsUserBill map=new FsUserBill();
        map.setCategory(CATEGORY_3.getValue());
        map.setBusinessId(order.getId().toString());
        map.setBillType(1);
        List<FsUserBill> list=billService.selectFsUserBillList(map);
        if(list!=null&&list.size()>0){
            for(FsUserBill bill:list){
                FsUser tuiUser= fsUserMapper.selectFsUserByIdForUpdate(bill.getUserId());
                if(tuiUser!=null){
                    FsUser tuiUserMap=new FsUser();
                    tuiUserMap.setUserId(tuiUser.getUserId());
                    tuiUserMap.setNowMoney(tuiUser.getNowMoney().add(new BigDecimal(bill.getNumber())));
                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(new BigDecimal(bill.getNumber())));
                    fsUserMapper.updateFsUser(tuiUserMap);
                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),bill.getNumber().doubleValue(),tuiUserMap.getBrokeragePrice().doubleValue(),"订单分佣金",order.getId().toString(),bill.getTuiUserId());
                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_1.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),bill.getNumber().doubleValue(),tuiUserMap.getNowMoney().doubleValue(),"订单分佣金",order.getId().toString(),bill.getTuiUserId());
                }
            }
        }
        FsStoreOrder orderMap=new FsStoreOrder();
        orderMap.setId(order.getId());
        orderMap.setTuiUserMoneyStatus(1);
        storeOrderMapper.updateFsStoreOrder(orderMap);
    }

    @Override
    public FsUser selectFsUserByMaOpenId(String openid) {
        return fsUserMapper.selectFsUserByMaOpenId(openid);
    }

    @Override
    public FsUser selectFsUserByMaOpenIdNew(String openid) {
        return fsUserMapper.selectFsUserByMaOpenIdNew(openid);
    }

    @Override
    public FsUser selectFsUserByMpOpenId(String openid) {
        return fsUserMapper.selectFsUserByMpOpenId(openid);
    }

    @Override
    public FsUser selectFsUserByUnionId(String unionId) {
        return fsUserMapper.selectFsUserByUnionId(unionId);
    }

    @Override
    public FsUser selectFsUserByUnionIdNew(String unionId) {
        return fsUserMapper.selectFsUserByUnionIdNew(unionId);
    }

    @Override
    public FsUser selectFsUserByUserCode(String userCode) {
        return fsUserMapper.selectFsUserByUserCode(userCode);
    }
    @Autowired
    FsUserTuiMoneyRankMapper fsUserTuiMoneyRankMapper;

    @Override
    public List<FsUserShareVO> selectFsUserShareList(String userId,Integer type) {
        if (type==null||type==0){
            type=3;
        }
        return fsUserTuiMoneyRankMapper.selectFsUserShareList(type);
    }

    @Override
    public R loginByMiniApp(LoginMpWxParam param) {
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }
        try {
            WxMaService wxService = WxMaConfiguration.getMaService(maProperties.getConfigs().get(0).getAppid());

            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            FsUser user=fsUserMapper.selectFsUserByMaOpenIdOrUnionId(session.getOpenid(),session.getUnionid());

            String ip = IpUtil.getRequestIp();
            if(ObjectUtil.isNull(user)) {
                // 保存用户信息
                user = saveUser(param, wxService, session, ip);
            } else {
                // 异步更新用户IP信息
                FsUser finalUser = user;
                CompletableFuture.runAsync(() -> {
                    try {
                        updateUserLastIp(finalUser, ip, session);
                    } catch (Exception e) {
                        logger.error("更新用户IP异常", e);
                    }
                });
            }
            String token = jwtUtils.generateToken(user.getUserId());
            return R.ok("登录成功").put("token",token).put("user", user);
        } catch (WxErrorException e) {
            return R.error("授权失败,"+e.getMessage());
        }
    }

    private FsUser saveUser(LoginMpWxParam param, WxMaService wxService, WxMaJscode2SessionResult session, String ip) {
        FsUser user;
        // 解密
        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
        //写入
        user=new FsUser();
        user.setPhone(phoneNoInfo.getPhoneNumber());
        logger.info("加密前的电话号码：" + phoneNoInfo.getPhoneNumber());
        Pattern PHONE_PATTERN = Pattern.compile("^1\\d{10}$");
        if (PHONE_PATTERN.matcher(phoneNoInfo.getPhoneNumber().trim()).matches()){
            user.setPhone(encryptPhone(user.getPhone()));
            logger.info("加密后的电话号码：" + user.getPhone());
        }
        user.setNickname("微信用户");
        user.setStatus(1);
        user.setMaOpenId(session.getOpenid());
        user.setLastIp(ip);
        user.setIsWeixinAuth(0);
        user.setCreateTime(new Date());
        if(StringUtils.isNotEmpty(session.getUnionid())){
            user.setUnionId(session.getUnionid());
        }
        this.insertFsUser(user);
        return user;
    }

    @Override
    public void updateUserLastIp(FsUser user, String ip, WxMaJscode2SessionResult session) {
        FsUser userMap=new FsUser();
        userMap.setUserId(user.getUserId());
        userMap.setUpdateTime(new DateTime());
        userMap.setLastIp(ip);
        if(StringUtils.isNotEmpty(session.getUnionid())){
            userMap.setUnionId(session.getUnionid());
        }
        if(StringUtils.isNotBlank(session.getOpenid())) {
            userMap.setMaOpenId(session.getOpenid());
        }
        this.updateFsUser(userMap);
    }


}
