package com.miaxis.wx.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.miaxis.common.config.WxPayConfigImpl;
import com.miaxis.common.config.WxpayConfig;
import com.miaxis.common.core.domain.entity.UserInfo;
import com.miaxis.common.exception.CustomException;
import com.miaxis.common.utils.RSAUtils;
import com.miaxis.common.utils.SecurityUtils;
import com.miaxis.common.utils.StringUtils;
import com.miaxis.common.utils.XmlUtil;
import com.miaxis.extension.service.IWxExtensionIncomeService;
import com.miaxis.feign.dto.WxGzhMini;
import com.miaxis.feign.dto.WxMessageTemplate;
import com.miaxis.feign.service.IWxSendService;
import com.miaxis.system.service.ISysConfigService;
import com.miaxis.user.service.IUserInfoService;
import com.miaxis.wx.domain.WxExtract;
import com.miaxis.wx.domain.WxExtractBank;
import com.miaxis.wx.domain.WxOrder;
import com.miaxis.wx.dto.QuerySchoolOrderListDTO;
import com.miaxis.wx.dto.WxExtractBankDTO;
import com.miaxis.wx.mapper.WxOrderMapper;
import com.miaxis.wx.service.IWxExtractBankService;
import com.miaxis.wx.service.IWxExtractService;
import com.miaxis.wx.service.IWxGzhService;
import com.miaxis.wx.service.IWxOrderService;
import com.miaxis.wx.vo.WxSchoolOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static com.miaxis.common.utils.OrderCodeFactory.getOrderCode;

/**
 * 电影订单Service业务层处理
 *
 * @author miaxis
 * @date 2021-05-07
 */
@Service
@Slf4j
public class WxOrderServiceImpl extends ServiceImpl<WxOrderMapper, WxOrder> implements IWxOrderService {
    @Resource
    private WxOrderMapper wxOrderMapper;



    @Autowired
    private IWxExtractService wxExtractService;

    @Autowired
    private ISysConfigService configService;


    @Autowired
    private IUserInfoService userInfoService;


    @Autowired
    private WxpayConfig wxpayConfig;


    @Autowired
    private RSAUtils rsaUtils;

    @Autowired
    private IWxSendService wxSendService;

    @Autowired
    private IWxGzhService wxGzhService;

    @Autowired
    private IWxExtensionIncomeService wxExtensionIncomeService;

    @Autowired
    private IWxExtractBankService wxExtractBankService;

    @Value("${app.appid}")
    private String appid;




    @Override
    public void createVipOrder(WxOrder wxOrder) {
        String price = configService.selectConfigByKey("vip_price");
        Double dprice = Double.valueOf(price);
        Double v =dprice* 100;
        wxOrder.setTotal(v.intValue());


    }
    @Override
    public WxOrder getByOutTradeNo(String outTradeNo) {
        return wxOrderMapper.getByOutTradeNo(outTradeNo);
    }

    @Override
    public List<WxSchoolOrder> QuerySchoolOrderList(QuerySchoolOrderListDTO dto) {
        return wxOrderMapper.QuerySchoolOrderList(dto);
    }

    @Override
    @Transactional
    public String wxwithdrawal(Integer amount) throws Exception {
        UserInfo student = SecurityUtils.getLoginUser().getStudent();
        UserInfo dbUserInfo = userInfoService.getById(student.getId());
        if (dbUserInfo.getProfitPrice() < amount){
            throw new CustomException("提现金额不能大于可提现金额");
        }

        Map<String, String> sortMap = new TreeMap<String, String>();
        sortMap.put("mch_appid",appid);
        sortMap.put("mchid",wxpayConfig.getMerchantId());
        sortMap.put("nonce_str", RandomStringUtils.randomAlphanumeric(32));
        sortMap.put("partner_trade_no",getOrderCode(null));
        sortMap.put("openid",student.getOpenid());
        sortMap.put("check_name","NO_CHECK");
        sortMap.put("amount",String.valueOf(amount));
        sortMap.put("desc","用户提现");

        WXPayConfig config = new WxPayConfigImpl();
        String sign = WXPayUtil.generateSignature(sortMap, config.getKey(), WXPayConstants.SignType.MD5);
        sortMap.put("sign", sign);
        WXPay pay = new WXPay(config);

        String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
        Map<String, String> resMap;
        String xmlStr = pay.requestWithCert(url, sortMap, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs());
        resMap = XmlUtil.xmlToMap(xmlStr);
        if (!"SUCCESS".equals(resMap.get("return_code"))||!"SUCCESS".equals(resMap.get("result_code"))){
            throw new CustomException(resMap.get("return_msg"));
        }
        //新增提现记录
        WxExtract wxExtract = new WxExtract();
        wxExtract.setOpenid(student.getOpenid());
        wxExtract.setExtractPrice(amount);
        wxExtract.setPartnerTradeNo(resMap.get("partner_trade_no"));
        wxExtract.setStatus("1");
        wxExtractService.save(wxExtract);

        //更新余额
        dbUserInfo.setProfitPrice(dbUserInfo.getProfitPrice()-amount);
        userInfoService.updateById(dbUserInfo);

        return resMap.get("return_msg");
    }

    @Override
    @Transactional
    public String wxwithbankdrawal(WxExtractBankDTO dto) throws Exception {
        UserInfo student = SecurityUtils.getLoginUser().getStudent();
        UserInfo dbUserInfo = userInfoService.getById(student.getId());
        if (dbUserInfo.getSaleType()!= 2 && dbUserInfo.getSaleType()!= 3){
            throw new CustomException("该用户类型不支持银行卡提现");
        }
        if (dbUserInfo.getProfitPrice() < dto.getAmount()){
            throw new CustomException("提现金额不能大于可提现金额");
        }

        Map<String, String> sortMap = new TreeMap<String, String>();
        sortMap.put("mch_id",wxpayConfig.getMerchantId());
        sortMap.put("nonce_str", RandomStringUtils.randomAlphanumeric(32));
        sortMap.put("partner_trade_no",getOrderCode(null));
        sortMap.put("amount",String.valueOf(dto.getAmount()));
        sortMap.put("desc","用户银行卡提现");




        // 进行签名服务

        sortMap.put("enc_true_name",rsaUtils.encryptData(dto.getEncTrueName()) );
        sortMap.put("enc_bank_no",rsaUtils.encryptData(dto.getEncBankNo()));
        sortMap.put("bank_code",dto.getBankCode().toString());


        WXPayConfig config = new WxPayConfigImpl();
        String sign = WXPayUtil.generateSignature(sortMap, config.getKey(), WXPayConstants.SignType.MD5);
        sortMap.put("sign", sign);
        WXPay pay = new WXPay(config);

        String url = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
        Map<String, String> resMap;
        String xmlStr = pay.requestWithCert(url, sortMap, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs());
        resMap = XmlUtil.xmlToMap(xmlStr);
        if (!"SUCCESS".equals(resMap.get("return_code"))||!"SUCCESS".equals(resMap.get("result_code"))){
            throw new CustomException(resMap.get("return_msg"));
        }
        //新增提现记录
        WxExtract wxExtract = new WxExtract();
        wxExtract.setOpenid(student.getOpenid());
        wxExtract.setExtractPrice(dto.getAmount());
        wxExtract.setPartnerTradeNo(resMap.get("partner_trade_no"));
        wxExtract.setStatus("1");
        wxExtractService.save(wxExtract);

        //如果此卡之前未存储，则加入到银行卡列表
        List<WxExtractBank> bankList = wxExtractBankService.list(new QueryWrapper<WxExtractBank>().eq("enc_bank_no", dto.getEncBankNo()));
        if (CollectionUtils.isEmpty(bankList)){
            WxExtractBank wxExtractBank = new WxExtractBank();
            wxExtractBank.setBankCode(dto.getBankCode());
            wxExtractBank.setEncBankNo(dto.getEncBankNo());
            wxExtractBank.setEncTrueName(dto.getEncTrueName());
            wxExtractBank.setOpenid(SecurityUtils.getLoginUser().getStudent().getOpenid());
            wxExtractBankService.save(wxExtractBank);
        }


        //更新余额
        dbUserInfo.setProfitPrice(dbUserInfo.getProfitPrice()-dto.getAmount());
        userInfoService.updateById(dbUserInfo);

        return resMap.get("return_msg");
    }

    @Override
    @Transactional
    public void writeNotifyDataToDb(JSONObject jsonObject) {
        //更新订单
        String outTradeNo = jsonObject.getString("out_trade_no");
        WxOrder wxOrder = this.getByOutTradeNo(outTradeNo);
        if (wxOrder == null) {
            throw new CustomException("该订单不存在");
        }
        //幂等性判定
//        if (!StringUtils.isEmpty(wxOrder.getTradeState())){
//            return ;
//        }
        wxOrder.setTransactionId(jsonObject.getString("transaction_id"));
        JSONObject amount = jsonObject.getJSONObject("amount");
        wxOrder.setPayerTotal(amount.getInteger("payer_total"));
        wxOrder.setTotal(amount.getInteger("total"));
        wxOrder.setCurrency(amount.getString("currency"));
        wxOrder.setPayerCurrency(amount.getString("payer_currency"));
        wxOrder.setTradeState(jsonObject.getString("trade_state"));
        wxOrder.setBankType(jsonObject.getString("bank_type"));
        DateTime dateTime  = new DateTime(jsonObject.getString("success_time"));
        wxOrder.setSuccessTime(dateTime.toDate());
        wxOrder.setTradeStateDesc(jsonObject.getString("trade_state_desc"));
        wxOrder.setTradeType(jsonObject.getString("trade_type"));
        wxOrder.setAttach(jsonObject.getString("attach"));
        JSONObject sceneInfo = jsonObject.getJSONObject("scene_info");
        if (sceneInfo != null){
            wxOrder.setDeviceId(sceneInfo.getString("device_id"));
        }
        this.updateById(wxOrder);

        //成为会员
        String data = wxOrder.getOrderDataJson();
        int days;
        try{
            days = Integer.valueOf(data);
        }catch (Exception e){
            throw new CustomException("参数值转化异常，请检查数据是否为数值类型");
        }
        long timeMillis = days*1440*60*1000l;
        UserInfo userinfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("union_id", wxOrder.getUnionId()));
        Date expireTime = userinfo.getExpireTime();
        if (expireTime == null || expireTime.getTime()< System.currentTimeMillis()){
            userinfo.setExpireTime(new Date(System.currentTimeMillis()+timeMillis));
        }else{
            userinfo.setExpireTime(new Date(expireTime.getTime()+timeMillis));
        }
        userInfoService.updateById(userinfo);

        //发送模板消息
        if (wxOrder.getOpenid()!=null){
            messageTemplateSend(userinfo,wxOrder);

            // 分成
            wxExtensionIncomeService.addExtensionIncomeBySourceId(wxOrder.getOutTradeNo(),wxOrder.getOpenid(),wxOrder.getTotal());
        }


    }

    @Override
    public Integer getTotalPay(QuerySchoolOrderListDTO dto) {
        return wxOrderMapper.getTotalPay(dto);
    }

    /**
     * 发送模板信息
     * @param userInfo 用户信息
     * @param wxOrder 订单信息
     */
    private void messageTemplateSend(UserInfo userInfo,WxOrder wxOrder){

        //获取tolen
        String token = wxGzhService.getGzhToken();

        WxMessageTemplate messageTemplate = new WxMessageTemplate();
        messageTemplate.setTouser(userInfo.getOpenid());
        messageTemplate.setTemplate_id("d1P87FFAAos_sHteTCA-slkFJesE8xkoDsRImVa58jc");
        messageTemplate.setUrl("https://jpcj-h5.zzxcx.net");
        WxGzhMini wxGzhMini = new WxGzhMini();
        messageTemplate.setMiniprogram(wxGzhMini);

        JSONObject jsonObject = new JSONObject();
        JSONObject first = new JSONObject();
        JSONObject keyword1 = new JSONObject();
        JSONObject keyword2 = new JSONObject();
        JSONObject keyword3 = new JSONObject();
        JSONObject keyword4 = new JSONObject();
        JSONObject keyword5 = new JSONObject();
        JSONObject remark = new JSONObject();
        first.put("value","恭喜您开通金牌车教会员成功！");
        first.put("color","#173177");
        keyword1.put("value","VIP会员");
        keyword1.put("color","#173177");
        keyword2.put("value", userInfo.getNickName());
        keyword2.put("color","#173177");
        keyword3.put("value","支付成功");
        keyword3.put("color","#173177");
        keyword4.put("value",wxOrder.getTotal()/100);
        keyword4.put("color","#173177");
        keyword5.put("value", DateUtil.format(userInfo.getExpireTime(), "yyyy-MM-dd HH:mm"));
        keyword5.put("color","#173177");
        remark.put("value","即日起，即可想享受会员特权");
        remark.put("color","#173177");
        jsonObject.put("first",first);
        jsonObject.put("keyword1",keyword1);
        jsonObject.put("keyword2",keyword2);
        jsonObject.put("keyword3",keyword3);
        jsonObject.put("keyword4",keyword4);
        jsonObject.put("keyword5",keyword5);
        jsonObject.put("remark",remark);
        messageTemplate.setData(jsonObject);
        String result = wxSendService.messageTemplateSend(token,messageTemplate);
        JSONObject parseObject = JSONObject.parseObject(result);
        log.info("模板消息：[{}],响应信息：[{}]",messageTemplate,parseObject);

    }


}
