package com.chaozhanggui.admin.system.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.chaozhanggui.admin.system.util.RedisCst;
import com.chaozhanggui.admin.system.util.RedisUtil;
import com.chaozhanggui.admin.system.util.StringUtil;
import com.chaozhanggui.admin.system.util.TokenUtil;
import com.chaozhanggui.common.system.config.RespBody;
import com.chaozhanggui.dao.system.dao.*;
import com.chaozhanggui.dao.system.entity.*;
import com.chaozhanggui.dao.system.model.CashStatus;
import com.chaozhanggui.dao.system.util.N;
import com.chaozhanggui.system.service.AliPayService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class Userservice {


    @Autowired
    TbPlussUserInfoMapper userInfoMapper;

    @Autowired
    TbPlussUserPromotionMapper tbPlussUserPromotionMapper;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    TbPlussCashMapper tbPlussCashMapper;

    @Autowired
    TbPlussCashAccountMapper tbPlussCashAccountMapper;


    @Autowired
    TbPlussMerchantBaseInfoMapper baseInfoMapper;
    @Resource
    AliPayService aliPayService;

    @Autowired
    TbPlussUserAccountMapper tbPlussUserAccountMapper;

    @Autowired
    TbPlussUserAccountFlowMapper tbPlussUserAccountFlowMapper;

    public RespBody doLogin(String loginName,String password,String userType,String ip) throws Exception {
        Boolean flag=false;
        if("FO".equals(userType)||"SO".equals(userType)||"MG".equals(userType)){
            flag=true;
        }
        if(!flag){
            log.error("非机构用户不允许登录:{}",userType);
            return new RespBody("000003");
        }

        TbPlussUserInfo tbPlussUserInfo= userInfoMapper.selectByLoginName(loginName);
        if(ObjectUtil.isEmpty(tbPlussUserInfo)){
            log.error("用户名不存在:{}",loginName);
            return new RespBody("000001");
        }

        TbPlussUserPromotion promotion=tbPlussUserPromotionMapper.selectByPrimaryKey(tbPlussUserInfo.getId().intValue());
        if(ObjectUtil.isEmpty(promotion)){
            log.error("不存在的用户类型");
            return new RespBody("000002");
        }

        if(!promotion.getTypeCode().equals(userType)){
            log.error("用户身份不匹配");
            return new RespBody("000004");
        }

        if (!tbPlussUserInfo.getPassword().equals(new MD5().digestHex(password,"UTF-8" ))) {
            log.error("message", "用户名或者密码错误");
            return new RespBody("000005");
        }

        String token= TokenUtil.generateToken(tbPlussUserInfo.getId().toString(),loginName,promotion.getTypeCode());
        Map<String,Object> map=new HashMap<>();
        map.put("token",token);
        Map<String,Object> userInfo=new HashMap<>();
        userInfo.put("userId",tbPlussUserInfo.getId());
        userInfo.put("userType",promotion.getTypeCode());
        userInfo.put("loginName",loginName);
        userInfo.put("ip",ip);
        map.put("user",userInfo);
        redisUtil.saveMessage(RedisCst.ONLINE_USER.concat(":").concat(loginName), JSONUtil.toJsonStr(map));
        return new RespBody("000000",map);

    }


    public RespBody outLogin(String loginName) throws Exception{
        redisUtil.deleteByKey(RedisCst.ONLINE_USER.concat(":").concat(loginName));
        return new RespBody("000000");
    }


    public RespBody getUserInfoByToken(String loginName,String token) throws Exception{

        String userInfo=  redisUtil.getMessage(RedisCst.ONLINE_USER.concat(":").concat(loginName));
        if(ObjectUtil.isEmpty(userInfo)){
            log.error("token 不存在或已经过期");
            return new RespBody("999999");
        }

        JSONObject object=JSONObject.parseObject(userInfo);
        if(!object.containsKey("token")||!token.equals(object.getString("token"))){
            log.error("token 不存在或已经过期");
            return new RespBody("999999");
        }

        if(!object.containsKey("user")||!object.getJSONObject("user").containsKey("loginName")||!loginName.equals(object.getJSONObject("user").getString("loginName"))){
            log.error("用户信息错误");
            return new RespBody("000006");
        }

        return new RespBody("000000",object.getJSONObject("user"));
    }

    public RespBody getIndexData(Integer userId){
        Map<String,Object>  map= userInfoMapper.selectIndexData(userId);
        if(ObjectUtil.isEmpty(map)||map.size()<=0){
            TbPlussUserPromotion userPromotion=   userPromotionMapper.selectByPrimaryKey(userId);
            map=new HashMap<>();
            map.put("sumConsumeFee",0);
            map.put("yestedayConsumeFee",0);
            map.put("sumfansShareMoney",0);
            map.put("yestedayShareMoney",0);
            map.put("currentFee",ObjectUtil.isEmpty(userPromotion)?0:userPromotion.getCurrentFee());

        }
        return new RespBody("000000",map);
    }


    public RespBody getDayOrder(String userId){
        if(ObjectUtil.isEmpty(userId)){
            log.error("参数错误");
            return new RespBody("000019");
        }
        return new RespBody("000000",userInfoMapper.selectOrderByDay(userId));
    }

    public  RespBody getDayProfit(String userId){
        if(ObjectUtil.isEmpty(userId)){
            log.error("参数错误");
            return new RespBody("000019");
        }

        return new RespBody("000000",userInfoMapper.selectProfitByDay(userId));
    }


    public  RespBody getMonth(String userId,String year){
        if(ObjectUtil.isEmpty(userId)){
            log.error("参数错误");
            return new RespBody("000019");
        }

        if(ObjectUtil.isEmpty(year)){
            year=StringUtil.getYear();
        }
        return new RespBody("000000",userInfoMapper.selectProfitByMonth(userId,year));
    }


    public  RespBody getMonthOrder(String userId,String year){
        if(ObjectUtil.isEmpty(userId)){
            log.error("参数错误");
            return new RespBody("000019");
        }
        if(ObjectUtil.isEmpty(year)){
            year=StringUtil.getYear();
        }
        return new RespBody("000000",userInfoMapper.selectOrderByMonth(userId,year));
    }

    @Autowired
    TbPlussUserPromotionMapper userPromotionMapper;
    public RespBody getOutFlow(String userId,String userName,String merchantCode,String status,Integer pageNum,Integer pageSize){
        TbPlussUserPromotion userPromotion= userPromotionMapper.selectByPrimaryKey(Integer.valueOf(userId));
        PageHelper.startPage(pageNum, pageSize);
        List<Map<String,Object>> list= userInfoMapper.selectOutFlow(userId,userName,merchantCode,status);
        list=list.stream().filter(it->{
            Boolean flag=false;
            Map<String,String> map=new HashMap<>();
            if(ObjectUtil.isNotEmpty(status)&&"0".equals(status)){
             JSONArray array=new JSONArray( it.get("cashStatus"))  ;
             for(int i=0;i<array.size();i++){
                 cn.hutool.json.JSONObject object=array.getJSONObject(i);
                 map.put(object.getStr("userType"),object.getStr("status"));
             }

             switch (it.get("typeCode").toString()){
                 case "MC":
                     if("SO".equals(userPromotion.getTypeCode())){
                         if("1".equals(map.get("AG"))&&"0".equals(map.get("SO"))){
                             flag=true;
                         }
                     }

                     if("FO".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("SO")) && "0".equals(map.get("FO"))) {
                             flag = true;
                         }
                     }

                     if("MG".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("FO")) && "0".equals(map.get("MG"))) {
                             flag = true;
                         }
                     }

                     break;
                 case "SB":
                     if("SO".equals(userPromotion.getTypeCode())){
                         if("1".equals(map.get("AG"))&&"0".equals(map.get("SO"))){
                             flag=true;
                         }
                     }

                     if("FO".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("SO")) && "0".equals(map.get("FO"))) {
                             flag = true;
                         }
                     }

                     if("MG".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("FO")) && "0".equals(map.get("MG"))) {
                             flag = true;
                         }
                     }
                     break;
                 case "FB":
                     if("SO".equals(userPromotion.getTypeCode())){
                         if("1".equals(map.get("AG"))&&"0".equals(map.get("SO"))){
                             flag=true;
                         }
                     }

                     if("FO".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("SO")) && "0".equals(map.get("FO"))) {
                             flag = true;
                         }
                     }

                     if("MG".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("FO")) && "0".equals(map.get("MG"))) {
                             flag = true;
                         }
                     }
                     break;
                 case "AG":
                     if("SO".equals(userPromotion.getTypeCode())){
                         if("0".equals(map.get("SO"))){
                             flag=true;
                         }
                     }

                     if("FO".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("SO")) && "0".equals(map.get("FO"))) {
                             flag = true;
                         }
                     }

                     if("MG".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("FO")) && "0".equals(map.get("MG"))) {
                             flag = true;
                         }
                     }
                     break;
                 case "SO":
                     if("FO".equals(userPromotion.getTypeCode())) {
                         if ("0".equals(map.get("FO"))) {
                             flag = true;
                         }
                     }

                     if("MG".equals(userPromotion.getTypeCode())) {
                         if ("1".equals(map.get("FO")) && "0".equals(map.get("MG"))) {
                             flag = true;
                         }
                     }
                     break;
                 case "FO":
                     if("MG".equals(userPromotion.getTypeCode())) {
                         if ( "0".equals(map.get("MG"))) {
                             flag = true;
                         }
                     }
                     break;
             }

            }else {
                flag=true;
            }

            return flag;

        }).collect(Collectors.toList());
        PageInfo pageInfo=new PageInfo(list);
        return new RespBody("000000",pageInfo);
    }


    public RespBody getUserOutFlow(String userId,String status,Integer pageNum,Integer pageSize){
        PageHelper.startPage(pageNum, pageSize);
        List<TbPlussCash> list=tbPlussCashMapper.selectCashByUserId(userId,status);
        PageInfo pageInfo=new PageInfo(list);
        return new RespBody("000000",pageInfo);
    }



    @Transactional(rollbackFor = Exception.class)
    public RespBody modifyOutFlow(Integer id,String userId,String status) throws Exception{
        if(ObjectUtil.isEmpty(id)||ObjectUtil.isEmpty(userId)||ObjectUtil.isEmpty(status)){
            log.error("参数错误");
            return new RespBody("000019");
        }
        TbPlussCash cash=  tbPlussCashMapper.selectByPrimaryKey(id);
        if(ObjectUtil.isEmpty(cash)){
            log.error("对应的提现信息不存在:{}",id);
            return new RespBody("000020");
        }

        if(cash.getStatus()==1 || cash.getStatus()==2){
            log.error("订单已处理完成: id :{}, status:{}",id,cash.getStatus());
            return new RespBody("000021");
        }

        TbPlussUserPromotion promotion= tbPlussUserPromotionMapper.selectByPrimaryKey(Integer.valueOf(userId));
        if(ObjectUtil.isEmpty(promotion)){
            log.error("审核员信息不存在");
            return new RespBody("000023");
        }


        Map<String,CashStatus> map=new HashMap<>();

        List<CashStatus> cashStatusList= JSONUtil.toList(new JSONArray(cash.getCashstatus()),CashStatus.class);

        if(ObjectUtil.isEmpty(cashStatusList)||cashStatusList.size()<=0){
            log.error("审核信息为空");
            return new RespBody("000024");
        }

        for (CashStatus cashStatus : cashStatusList) {
            map.put(cashStatus.getUserType(),cashStatus);
        }

        CashStatus cashStatus=null;

        CashStatus upStatus=null;
        switch (promotion.getTypeCode()){
            case "AG":
                if(!map.containsKey("AG")){
                    cashStatus=new CashStatus();
                    cashStatus.setStatus("1");
                }else {
                    cashStatus=map.get("AG");
                }

                upStatus=map.get("SO");
                break;
            case "SO":
                if(!map.containsKey("AG")){
                    cashStatus=new CashStatus();
                    cashStatus.setStatus("1");
                }else {
                    cashStatus=map.get("AG");
                }

                upStatus=map.get("FO");
                break;
            case "FO":
                if(!map.containsKey("SO")){
                    cashStatus=new CashStatus();
                    cashStatus.setStatus("1");
                }else {
                    cashStatus=map.get("SO");
                }

                upStatus=map.get("MG");
                break;
            case "MG":
                if(!map.containsKey("FO")){
                    cashStatus=new CashStatus();
                    cashStatus.setStatus("1");
                }else {
                    cashStatus=map.get("FO");
                }
                upStatus=map.get("MG");
                break;
        }
//        if(!userId.equals(cashStatus.getUserId().toString())){
//            log.error("操作权限不足");
//            return new RespBody("000025");
//        }

        if("0".equals(cashStatus.getStatus())){
            log.error("请等待下级审核完成");
            return new RespBody("000026");
        }

        if("2".equals(cashStatus.getStatus())){
            log.error("提现已被拒绝");
            return new RespBody("000027");
        }

        if(!upStatus.getStatus().equals("0")){
            log.error("已被上级审核");
            return new RespBody("000028");
        }



        switch (status){
            case "1":
                cashStatusList.stream().filter(it->{
                    if(it.getUserId().toString().equals(userId))
                        it.setStatus("1");
                    return true;
                }).collect(Collectors.toList());

                if(promotion.getTypeCode().equals("MG")){
                    cash.setStatus(1);
                    AlipayFundTransUniTransferResponse response = aliPayService.alipayTransfer(cash.getVirrealcashamt().toString(), cash.getAccountno(), cash.getAccountname(), "", cash.getCashnumber());
                    if (response.isSuccess() && response.getStatus().equals("SUCCESS")){
                        modFunds(cash.getUserid(),cash.getCashamt());
                    }else {
                        return new RespBody("000071");
                    }

                }
                cash.setCashstatus(JSONUtil.toJsonStr(cashStatusList));


                break;
            case "2":
                cashStatusList.stream().filter(it->{
                    if(it.getUserId().toString().equals(userId))
                        it.setStatus("2");
                    if(it.getUserType().equals("MG")){
                        //释放资金
                        TbPlussUserAccount userAccount=  tbPlussUserAccountMapper.selectByPrimaryKey(cash.getUserid());
                        if(ObjectUtil.isEmpty(userAccount)|| N.gt(cash.getCashamt(),userAccount.getFreezeBalance())){
                            try {
                                throw new Exception("冻结资金不足");
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }

                        userAccount.setFreezeBalance(userAccount.getFreezeBalance().subtract(cash.getCashamt()));
                        userAccount.setUpdateTime(new Date());
                        tbPlussUserAccountMapper.updateByPrimaryKey(userAccount);

                        TbPlussUserAccountFlow flow=new TbPlussUserAccountFlow();

                        flow.setUserId(cash.getUserid());
                        flow.setBizCode("105");
                        flow.setBizName("提现拒绝解冻");
                        flow.setAmount(cash.getCashamt());
                        flow.setBalance(userAccount.getBalance());
                        flow.setCreateTime(new Date());
                        tbPlussUserAccountFlowMapper.insert(flow);
                    }
                    return true;
                }).collect(Collectors.toList());
                cash.setStatus(2);
                cash.setCashstatus(JSONUtil.toJsonStr(cashStatusList));
                break;
            default:
                log.error("错误的操作类型");
                return new RespBody("000022");
        }

        tbPlussCashMapper.updateByPrimaryKey(cash);
        return new RespBody("000000");

    }


    public void modFunds(Integer userId,BigDecimal amount) throws Exception {
        //释放资金，扣除资金
        TbPlussUserAccount userAccount=  tbPlussUserAccountMapper.selectByPrimaryKey(userId);
        if(ObjectUtil.isEmpty(userAccount)|| N.gt(amount,userAccount.getFreezeBalance())){
            throw new Exception("冻结资金不足");
        }
        userAccount.setFreezeBalance(userAccount.getFreezeBalance().subtract(amount));
        userAccount.setBalance(userAccount.getBalance().subtract(amount));
        userAccount.setUpdateTime(new Date());
        tbPlussUserAccountMapper.updateByPrimaryKey(userAccount);

        TbPlussUserAccountFlow flow=new TbPlussUserAccountFlow();
        flow.setUserId(userId);
        flow.setBizCode("105");
        flow.setBizName("提现解冻");
        flow.setAmount(amount);
        flow.setBalance(userAccount.getBalance());
        flow.setCreateTime(new Date());
        tbPlussUserAccountFlowMapper.insert(flow);


        flow=new TbPlussUserAccountFlow();
        flow.setUserId(userId);
        flow.setBizCode("106");
        flow.setBizName("提现扣除");
        flow.setAmount(amount);
        flow.setBalance(userAccount.getBalance());
        flow.setCreateTime(new Date());
        tbPlussUserAccountFlowMapper.insert(flow);



    }

    public RespBody getUserBalance(String userId){
        Map<String, BigDecimal> map=new HashMap<>();

       BigDecimal profit= tbPlussCashMapper.selectByUserId(userId);

       BigDecimal fronzenAmt=tbPlussCashMapper.selectCashFrozenAmountByUserId(userId);

       BigDecimal successAmt=tbPlussCashMapper.selectCashAmt(userId);

       map.put("sumProfit",profit);
       map.put("fronZenAmt",fronzenAmt);
       map.put("successAmt",successAmt);
       map.put("availableBalance",profit.subtract(fronzenAmt).subtract(successAmt));
        return new RespBody("000000",map);

    }


    @Transactional(rollbackFor = Exception.class)
    public RespBody withdrawalProfit(String userId,BigDecimal amount) throws Exception{


        TbPlussUserInfo userInfo= userInfoMapper.selectByPrimaryKey(Long.valueOf(userId));

        if(ObjectUtil.isEmpty(userInfo)){
            log.error("用户不存在");
            return new RespBody("000007");
        }

        TbPlussUserPromotion promotion= userPromotionMapper.selectByPrimaryKey(Integer.valueOf(userId));
        if(ObjectUtil.isEmpty(promotion)){
            log.error("用户不存在");
            return new RespBody("000007");
        }

        if(promotion.getTypeCode().equals("MG")){
            log.error("平台不允许提现");
            return new RespBody("000033");
        }



        if(amount.compareTo(BigDecimal.TEN)<0){
            log.error("小于最小提现金额");
            return new RespBody("000032");
        }


        TbPlussUserAccount userAccount= tbPlussUserAccountMapper.selectByPrimaryKey(Integer.valueOf(userId));
        if(ObjectUtil.isEmpty(userAccount)|| N.gt(amount,userAccount.getBalance().subtract(userAccount.getFreezeBalance()))){
            log.error("可提余额不足:{},{},{}",userId,amount,userAccount.getBalance().subtract(userAccount.getFreezeBalance()));
            return new RespBody("000029");
        }


//        TbPlussCashAccount account= tbPlussCashAccountMapper.selectByUserId(userId);
//        if(ObjectUtil.isEmpty(account)){
//            log.error("提现账户信息不完整");
//            return new RespBody("000030");
//        }



        TbPlussCash cash=new TbPlussCash();
        cash.setUserid(Integer.valueOf(userId));
        cash.setUsername(userInfo.getTruename());
        cash.setCashamt(amount);
        cash.setCreatedt(new Date());
        cash.setCashnumber(StringUtil.getBillno());
        cash.setType(1);
        cash.setStatus(0);
        cash.setBaseservicecharge(BigDecimal.valueOf(3));
        cash.setRatiocharge(cash.getCashamt().multiply(BigDecimal.valueOf(0.08)));
        cash.setCashstatus(JSONUtil.toJsonStr(getCashMap(promotion.getParentUserId(),new LinkedList<>())));
        tbPlussCashMapper.insertSelective(cash);


        userAccount.setFreezeBalance(userAccount.getFreezeBalance().add(amount));
        userAccount.setUpdateTime(new Date());
        tbPlussUserAccountMapper.updateByPrimaryKey(userAccount);

        TbPlussUserAccountFlow   flow=new TbPlussUserAccountFlow();
        flow.setUserId(Integer.valueOf(userId));
        flow.setBizCode("108");
        flow.setBizName("提现冻结");
        flow.setAmount(amount);
        flow.setBalance(userAccount.getBalance());
        flow.setCreateTime(new Date());
        tbPlussUserAccountFlowMapper.insert(flow);

        return new RespBody("000000");

    }



    public LinkedList<CashStatus> getCashMap(String userId, LinkedList<CashStatus> list){
        TbPlussUserPromotion promotion=userPromotionMapper.selectByPrimaryKey(Integer.valueOf(userId));
        if(ObjectUtil.isNotEmpty(promotion)&&"0".equals(promotion.getParentUserId())){
            CashStatus cashStatus=new CashStatus();
            cashStatus.setUserId(promotion.getUserId().toString());
            cashStatus.setUserType(promotion.getTypeCode());
            cashStatus.setStatus("0");
            cashStatus.setLoginName(promotion.getLoginName() == null?"null":promotion.getLoginName());
            list.add(cashStatus);
            promotion.setCashStatus(list);
            return list;

        }
        if("AG".equals(promotion.getTypeCode())||"SO".equals(promotion.getTypeCode())||"FO".equals(promotion.getTypeCode())){
            CashStatus cashStatus=new CashStatus();
            cashStatus.setUserId(promotion.getUserId().toString());
            cashStatus.setUserType(promotion.getTypeCode());
            cashStatus.setStatus("0");
            cashStatus.setLoginName(promotion.getLoginName());
            list.add(cashStatus);
            promotion.setCashStatus(list);
        }
        getCashMap(promotion.getParentUserId(),list);
        return list;
    }
}
