package com.pj.api.jh.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import com.pj.api.jh.task.CheckPayStatusTask;
import com.pj.api.jh.utils.JhHttpUtils;
import com.pj.api.jh.utils.MerchantApiUtil;
import com.pj.api.jh.bo.JhNotifyBO;
import com.pj.api.wx.bo.Attach;
import com.pj.api.wx.bo.NotifyBO;
import com.pj.api.wx.service.WxService;
import com.pj.current.config.JhConfig;
import com.pj.current.config.MyConfig;
import com.pj.current.config.PartConfig;
import com.pj.current.task.TaskService;
import com.pj.project.tb_order.TbOrder;
import com.pj.project.tb_order.TbOrderService;
import com.pj.project4sp.global.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: lzm
 * @Date: 2022/04/19/17:38
 */

@Service
@Transactional
@Slf4j
public class JhService {

    @Resource
    MyConfig myConfig;
    @Resource
    JhConfig jhConfig;
    @Resource
    PartConfig partConfig;
    @Resource
    WxService wxService;

    @Resource
    JhHttpUtils jhHttpUtils;
    @Resource
    private TbOrderService tbOrderService;
    @Resource
    private TaskService taskService;

    public Map<String, ?> initPay(HttpServletRequest request) throws Exception {
        if (!jhConfig.isEnable()) {
            return wxService.prePay(request);
        }
        String money = request.getParameter("money");
        if (Double.valueOf(money) <= 0) {
            throw new BusinessException("金额不正确");
        }
        String openid = request.getParameter("openid");
        String desc = request.getParameter("desc");
        String businessId = request.getParameter("b");
        String c = request.getParameter("c");
        String a = request.getParameter("a");
        String tradeType = request.getParameter("tradeType");
        String businessType = request.getParameter("businessType");
        Attach atchMap = new Attach();
        atchMap.setC(c).setB(businessId).setA(a);
        String out_trade_no = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + RandomUtil.randomNumbers(6);
        StaticLog.info("outTradeNo:{}", out_trade_no);
        Map<String, Object> params = new HashMap<>();
       // params.put("attach", JSONUtil.toJsonStr(atchMap));
        params.put("productType", jhConfig.getProductType());
        params.put("businessMerchantNo", jhConfig.getBusinessMerchantNo());
        params.put("openId", openid);
        params.put("merchantNo", jhConfig.getBusinessMerchantNo());
        params.put("tradeType", businessType);
        params.put("subTradeType", "");
        String total_free = partConfig.isTestEnv() ? "0.01" : money + "";
        log.info("order price:{}", total_free);
        params.put("orderPrice", total_free);
        params.put("outTradeNo", out_trade_no);
        params.put("productName", desc);
        params.put("orderIp", WxService.getIpAddress(request));
        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        params.put("orderTime", now);
        params.put("returnUrl", "");
        params.put("notifyUrl", myConfig.getDomain() + "/jh/notify");
        params.put("remark", desc);
        String paySecrit = jhConfig.getPaySecret();
        String sign = MerchantApiUtil.getSign(params, paySecrit);
        params.put("sign", sign);
        String jsonParam = JSONUtil.toJsonStr(params);
        String initPayUrl = jhConfig.getServerUrl() + "/uaps-web-gateway/cnpPay/initPay";
        String result = jhHttpUtils.postJson(initPayUrl, jsonParam);
        StaticLog.info("调用聚合支付返回:{}", result);
        JSONObject jsonResult = JSONUtil.parseObj(result);
        if (StrUtil.equals("0000", jsonResult.getStr("resultCode"))) {
            JSONObject payMessage = JSONUtil.parseObj(jsonResult.getStr("payMessage"));
            String p = payMessage.getStr("package");
            Map<String, String> r = wxService.getPayP(payMessage.getStr("timeStamp"), payMessage.getStr("nonceStr"), openid, p);
            StaticLog.info("re:{}", JSONUtil.toJsonStr(r));
            JSONObject object = JSONUtil.parseObj(payMessage);

            object.set("outTradeNo", out_trade_no);
            TbOrder tbOrder = new TbOrder();
            tbOrder.setAttach(JSONUtil.toJsonStr(atchMap))
                    .setOpenid(openid)
                    .setOrderTime(new Date())
                    .setOutTradeNo(out_trade_no).setPrice(money);
            tbOrderService.save(tbOrder);
            taskService.addTask(new CheckPayStatusTask(RandomUtil.randomNumbers(12), 2000, out_trade_no));
            return BeanUtil.beanToMap(object);
        }
        throw new Exception("生成订单失败");
      //  return new HashMap<>();
    }

    public Map<String, Object> buildCheckParams(String outTradeNo) {
        Map<String, Object> params = new HashMap<>();
        params.put("businessMerchantNo", jhConfig.getBusinessMerchantNo());
        params.put("outTradeNo", outTradeNo);
        String paySecrit = jhConfig.getPaySecret();
        String sign = MerchantApiUtil.getSign(params, paySecrit);
        params.put("sign", sign);
        return params;
    }

    public JSONObject checkPayResult(String outTradeNo) {
        String url = jhConfig.getServerUrl() + "/uaps-web-gateway/query/singleOrder";
        Map<String, Object> params = buildCheckParams(outTradeNo);
        String result = jhHttpUtils.postForm(url, params);
        return JSONUtil.parseObj(result);
    }

    @Async
    public void notifyResult(JhNotifyBO bo) {
        String orderStatus = bo.getTradeStatus();
        if (!"SUCCESS".equals(orderStatus) && !"FINISH".equals(orderStatus)) {
            log.error("支付订单回调失败:{}",JSONUtil.toJsonStr(bo));
            return;
        }
        NotifyBO notifyBO = new NotifyBO();
        notifyBO.setOutTradeNo(bo.getOutTradeNo())
                .setTransactionId(bo.getBankTrxNo()).setTimeEnd(bo.getSuccessTime())
                .setTotalFee(NumberUtil.mul(bo.getOrderPrice(), 100 + "").toString());
        wxService.WxNotify(notifyBO);
    }
}
