package com.org.hktshop.controller.pay;

import com.org.hktshop.Interface.product.IHktGoodsService;
import com.org.hktshop.base.BaseResult;
import com.org.hktshop.entity.order.HktOrder;
import com.org.hktshop.entity.order.HktOrderRefund;
import com.org.hktshop.entity.user.HktUser;
import com.org.hktshop.service.order.HktOrderRefundService;
import com.org.hktshop.service.order.HktOrderService;
import com.org.hktshop.service.user.HktUserPointService;
import com.org.hktshop.service.user.HktUserService;
import com.org.hktshop.service.user.HktUsersScoreService;
import com.org.hktshop.utils.DateUtil;
import com.org.hktshop.utils.HttpCode;
import com.org.hktshop.utils.IpUtils;
import com.org.hktshop.utils.pay.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @author owen
 */
@RestController
@RequestMapping(value = "/wxpay")
public class WxpayController extends PayBaseController {

    private static Logger logger = LoggerFactory.getLogger(WxpayController.class);

    @Autowired
    private HktOrderService hktOrderService;

    @Autowired
    private HktOrderRefundService hktOrderRefundService;

    @Autowired
    private PayMessageTips payMessageTips;

    @Autowired
    private IHktGoodsService hktGoodsService;

    @Autowired
    private HktUserPointService hktUserPointService;

    @Autowired
    private HktUserService userService;

    @Autowired
    private HktUsersScoreService scoreService;

    /**
     * 微信支付->扫码支付(模式二)->统一下单->微信二维码
     *
     * @param paramMap 订单号
     * @return
     */
    @PostMapping("/qrcode")
    public Object wxpayPay(HttpServletResponse response, HttpServletRequest request, @RequestBody Map paramMap) {

//        HktUser user = (HktUser) request.getSession().getAttribute("OpUser");


        BaseResult<Object> objectBaseResult = new BaseResult<>();
        //获取支付终端IP地址
        String ipAddress = IpUtils.getIPAddress(request);
        DecimalFormat df1 = new DecimalFormat("0");
        String urlCode = "";
        // 获取订单号
        String tradeNo = (String) paramMap.get("tradeNo");
        HktOrder findOrder = new HktOrder();
        findOrder.setOrderSn(tradeNo);
//        findOrder.setUserId(user.getId());
        HktOrder hktOrder = hktOrderService.getHktOrder(findOrder);
        if (hktOrder == null) {
            objectBaseResult.setHttpCode(HttpCode.BAD_REQUEST.getCode());
            objectBaseResult.setMessage("订单号不存在");
            return objectBaseResult;
        }
        if (!"0".equals(hktOrder.getOrderStatus())) {
            objectBaseResult.setHttpCode(HttpCode.MULTI_STATUS.getCode());
            objectBaseResult.setMessage("无效订单");
            return objectBaseResult;
        }
        /*String createTime = hktOrder.getCreateTime();
        Date date = DateUtil.StringToDate1(createTime);
        long creTime = date.getTime();
        Date date1 = new Date();
        long curTime = date1.getTime();
        if ((curTime - creTime) / (1000 * 60) > 30) {
            objectBaseResult.setHttpCode(HttpCode.MULTI_STATUS.getCode());
            objectBaseResult.setMessage("订单已失效，无法支付");
            return objectBaseResult;
        }*/

        String totalAmount = hktOrder.getTotalAmount();
        /*BigDecimal bigDecimal1 = new BigDecimal(totalAmount);
        String totalFeestr = (String) paramMap.get("totalFee");
        BigDecimal bigDecimal2 = new BigDecimal(totalFeestr);
        if(bigDecimal1.compareTo(bigDecimal2) != 0){
            objectBaseResult.setHttpCode(HttpCode.MULTI_STATUS.getCode());
            objectBaseResult.setMessage("非法操作");
            return objectBaseResult;
        }*/

        BigDecimal bigDecimal = new BigDecimal(totalAmount);
        BigDecimal multiply = bigDecimal.multiply(new BigDecimal(100));
        String totalFee = df1.format(multiply);
        String currTime = PayToolUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = String.valueOf(PayToolUtil.buildRandom(4));
        String nonce_str = strTime + strRandom;
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        //公众账号ID
        packageParams.put("appid", APPID);
        //商户号
        packageParams.put("mch_id", MCHID);
        //随机字符串
        packageParams.put("nonce_str", nonce_str);
        //商品描述
        packageParams.put("body", "订单支付");
        //商户订单号
        packageParams.put("out_trade_no", tradeNo + "_" + System.currentTimeMillis());
        //标价金额 订单总金额，单位为分
        packageParams.put("total_fee", totalFee);
        //终端IP APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP
        packageParams.put("spbill_create_ip", ipAddress);
        //通知地址 异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数
        packageParams.put("notify_url", NOTIFY_URL);
        //交易类型 NATIVE 扫码支付
        packageParams.put("trade_type", "NATIVE");
        //设置二维码有效时间
        packageParams.put("time_expire", DateUtil.getOrderExpireTime(15 * 60 * 1000L));
        // 签名
        String sign = PayToolUtil.createSign("UTF-8", packageParams, KEY);
        packageParams.put("sign", sign);
        // 将请求参数转换为xml格式的string
        String requestXML = PayToolUtil.getRequestXml(packageParams);
//        logger.info("requestXML:{}", requestXML);
        // 调用微信支付统一下单接口
        String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);
//        logger.info("resXml: {}", resXml);
        // 解析微信支付结果
        Map map = null;
        try {
            map = XMLUtil4jdom.doXMLParse(resXml);
//            logger.info("map: {}", map);
            if ("SUCCESS".equals((String) map.get("result_code"))) {
                urlCode = (String) map.get("code_url");
                logger.info("urlCode:{}", urlCode);
                objectBaseResult.setData(urlCode);
                objectBaseResult.setHttpCode(HttpCode.OK.getCode());
                return objectBaseResult;
            } else {
                objectBaseResult.setMessage((String) (map.get("err_code_des") != null ? map.get("err_code_des") : map.get("return_msg")));
                objectBaseResult.setHttpCode(HttpCode.BAD_REQUEST.getCode());
                return objectBaseResult;
            }
        } catch (Exception e) {
            objectBaseResult.setHttpCode(500);
            objectBaseResult.setMessage(e.getMessage());
            return objectBaseResult;
        }
    }

    /**
     * 回调
     *
     * @param request
     * @param response
     */
    @PostMapping("/notify")
    public String wxpayNotify(HttpServletRequest request, HttpServletResponse response) {
        System.out.print("############调用支付回调接口##############");
        //读取参数
        InputStream inputStream;
        StringBuffer sb = null;
        try {
            sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //解析xml成map
        Map<String, String> map = new HashMap<String, String>();
        try {
            map = XMLUtil4jdom.doXMLParse(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

        //过滤空 设置 TreeMap
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        Iterator it = map.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = map.get(parameter);
            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        //判断签名是否正确
        if (PayToolUtil.isTenpaySign("UTF-8", packageParams, KEY)) {
            String resXml = "";
            if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
                // 这里是支付成功
                String outTradeNo = (String) packageParams.get("out_trade_no");
                HktOrder hktOrder = new HktOrder();
                hktOrder.setOrderSn(outTradeNo.substring(0, outTradeNo.indexOf("_")));
                hktOrder.setOutTrandeNo(outTradeNo);
                hktOrder.setOrderStatus("1");
                hktOrder.setPayTime(DateUtil.getDateTime());
                hktOrder.setPayStatus("2");
                hktOrder.setPayName("微信");
//                hktOrder.set
                String sql = "select id,order_sn as orderSn,give_type as giveType,mobile from hkt_order where order_sn = " + outTradeNo.substring(0, outTradeNo.indexOf("_"));
                HktOrder hktOrderByNo = hktOrderService.getHktOrderByNo(sql);
                hktOrder.setId(hktOrderByNo.getId());
                hktOrderService.updateHktOrder(hktOrder);
                logger.info("################订单付款成功################");
                hktUserPointService.addUserPoint(hktOrder.getOrderSn());
               /* try{
                    HktUser hktUser = userService.getHktUserById(hktOrderByNo.getUserId());
                    scoreService.AddUserScore(hktUser,2,Integer.parseInt(hktOrderByNo.getTotalAmount()));
                    hktGoodsService.subtractStock(hktOrderByNo.getOrderSn());
                }catch (Exception e){
                    logger.info("########去除库存异常####### error={}",e.toString());
                }*/
                if(2 == hktOrderByNo.getGiveType()){
                    payMessageTips.sendMsg(hktOrderByNo);
                }
                logger.info("###########微信订单回调接口 参数:"+hktOrder.toString()+"################");
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

            } else {
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                return ("fail");
            }
            try {
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        } else {
            logger.info("通知签名验证失败");
        }
        return ("success");
    }


    /**
     * 退款申请接口
     */
//    @PostMapping("/wxPayRefund")
    public void wxPayRefund(HktOrderRefund hktOrderRefund) throws Exception{
            //订单编号
            String outTradeNo = hktOrderRefund.getOutTrandeNo();
            //退款单编号
            String outRefundNo =hktOrderRefund.getOutRefundNo();
            //订单金额(单位为分，只能是整数)
            Double totalAmount = hktOrderRefund.getTotalAmount();
            String totalFee = new BigDecimal(totalAmount + "").multiply(new BigDecimal("100")).intValue()+"";
            //退款金额(单位为分，只能是整数)
        String refundFee = new BigDecimal(hktOrderRefund.getRefundAmount()+"").multiply(new BigDecimal("100")).intValue()+"";
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();

            String currTime = PayToolUtil.getCurrTime();
            String strTime = currTime.substring(8, currTime.length());
            String strRandom = String.valueOf(PayToolUtil.buildRandom(4));
            String nonce_str = strTime + strRandom;
            //公众账号ID
            packageParams.put("appid", APPID);
            //商户号
            packageParams.put("mch_id", MCHID);
            //随机字符串
            packageParams.put("nonce_str", nonce_str);
            //商户订单号
            packageParams.put("out_trade_no", outTradeNo);
            //订单金额
            packageParams.put("total_fee", totalFee);
            //退款金额
            packageParams.put("refund_fee", refundFee);
            //退款订单号
            packageParams.put("out_refund_no", outRefundNo);
            //回调
//            packageParams.put("notify_url", REFUND_NOTIFY_URL);
            // 签名
            String sign = PayToolUtil.createSign("UTF-8", packageParams, KEY);
            logger.info("签名返回值："+sign);
            packageParams.put("sign", sign);
            // 将请求参数转换为xml格式的string
            String requestXML = PayToolUtil.getRequestXml(packageParams);
            logger.info("退款requestXML:{}", requestXML);
            // 调用微信支付统一下单接口
            String path = "/home/pay/apiclient_cert.p12";
            String resXml = HttpUtil.refundHttpRequest(MCHID, PayConfigUtil.REFUND_URL, requestXML, path);
            logger.info("退款调用返回 resXml:{}", resXml);
                Map resultMap = XMLUtil4jdom.doXMLParse(resXml);
                if ("SUCCESS".equals((String) resultMap.get("result_code"))) {
                    //回调退款成功接口
                    HktOrder hktOrder = new HktOrder();
                    hktOrder.setId(hktOrderRefund.getOrderId());
                    HktOrder hktOrderById = hktOrderService.getHktOrder(hktOrder);
                    hktOrder.setReturnStatus("1");
                    hktOrder.setOrderStatus("4");
                    hktOrderService.updateHktOrder(hktOrder);
                    hktOrderRefund.setOrderStatus("1");
                    hktOrderRefundService.updateOrderRefund(hktOrderRefund);

                    HktUser hktUser = userService.getHktUserById(hktOrderById.getUserId());
                    scoreService.AddUserScore(hktUser,2,(-1) *(Integer.parseInt(hktOrderById.getTotalAmount())));
                    logger.info("退款成功返回参数"+resultMap.toString());
                } else {
//                     回调退款失败接口
                    hktOrderRefund.setOrderStatus("0");
                    hktOrderRefund.setFailMsg(resultMap.get("return_msg")+"");
                    if("OK".equalsIgnoreCase(resultMap.get("return_msg")+"")){
                        hktOrderRefund.setFailMsg(resultMap.get("err_code_des")+"");
                    }
                    hktOrderRefundService.updateOrderRefund(hktOrderRefund);
                    logger.info("退款失败返回参数"+resultMap.toString());
                }
        }

        @PostMapping("/wmApp")
        public Object AppWxPay(HttpServletResponse response, HttpServletRequest request, @RequestBody Map paramMap){
            BaseResult<Object> objectBaseResult = new BaseResult<>();
            //获取支付终端IP地址
            String ipAddress = IpUtils.getIPAddress(request);
            DecimalFormat df1 = new DecimalFormat("0");
            String urlCode = "";
            // 获取订单号
            String tradeNo = (String) paramMap.get("tradeNo");
            HktOrder findOrder = new HktOrder();
            findOrder.setOrderSn(tradeNo);
//        findOrder.setUserId(user.getId());
            HktOrder hktOrder = hktOrderService.getHktOrder(findOrder);
            if (hktOrder == null) {
                objectBaseResult.setHttpCode(HttpCode.BAD_REQUEST.getCode());
                objectBaseResult.setMessage("订单号不存在");
                return objectBaseResult;
            }
            if (!"0".equals(hktOrder.getOrderStatus())) {
                objectBaseResult.setHttpCode(HttpCode.MULTI_STATUS.getCode());
                objectBaseResult.setMessage("无效订单");
                return objectBaseResult;
            }
            String createTime = hktOrder.getCreateTime();
            Date date = DateUtil.StringToDate1(createTime);
            long creTime = date.getTime();
            Date date1 = new Date();
            long curTime = date1.getTime();
            if ((curTime - creTime) / (1000 * 60) > 30) {
                objectBaseResult.setHttpCode(HttpCode.MULTI_STATUS.getCode());
                objectBaseResult.setMessage("订单已失效，无法支付");
                return objectBaseResult;
            }

            String totalAmount = hktOrder.getTotalAmount();

            BigDecimal bigDecimal = new BigDecimal(totalAmount);
            BigDecimal multiply = bigDecimal.multiply(new BigDecimal(100));
            String totalFee = df1.format(multiply);
            String currTime = PayToolUtil.getCurrTime();
            String strTime = currTime.substring(8, currTime.length());
            String strRandom = String.valueOf(PayToolUtil.buildRandom(4));
            String nonce_str = strTime + strRandom;
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            //公众账号ID
            packageParams.put("appid", APPID);
            //商户号
            packageParams.put("mch_id", MCHID);
            //随机字符串
            packageParams.put("nonce_str", nonce_str);
            //商品描述
            packageParams.put("body", "订单支付");
            //商户订单号
            packageParams.put("out_trade_no", tradeNo + "_" + System.currentTimeMillis());
            //标价金额 订单总金额，单位为分
            packageParams.put("total_fee", totalFee);
            //终端IP APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP
            packageParams.put("spbill_create_ip", ipAddress);
            //通知地址 异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数
            packageParams.put("notify_url", NOTIFY_URL);

            //交易类型 NATIVE 扫码支付
            packageParams.put("trade_type", "MWEB");
            //设置二维码有效时间
            packageParams.put("time_expire", DateUtil.getOrderExpireTime(15 * 60 * 1000L));
            // 签名
            String sign = PayToolUtil.createSign("UTF-8", packageParams, KEY);
            packageParams.put("sign", sign);
            // 将请求参数转换为xml格式的string
            String requestXML = PayToolUtil.getRequestXml(packageParams);
//        logger.info("requestXML:{}", requestXML);
            // 调用微信支付统一下单接口
            String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);
            Map map = null;
            try{
                map = XMLUtil4jdom.doXMLParse(resXml);
                SortedMap<Object, Object> parameterMap = new TreeMap<Object, Object>();
                parameterMap.put("appid", APPID);
                parameterMap.put("partnerid", MCHID);
                parameterMap.put("prepayid", map.get("prepay_id"));
                parameterMap.put("package", "prepay_id="+map.get("prepay_id"));

                parameterMap.put("noncestr", PayUtils.CreateNoncestr());
                // 本来生成的时间戳是13位，但是ios必须是10位，所以截取了一下
                parameterMap.put("timestamp", String.valueOf(System.currentTimeMillis()).toString().substring(0, 10));
                String sign1 = PayToolUtil.createSign("UTF-8", parameterMap, KEY);
                parameterMap.put("sign", sign1);
                objectBaseResult.setData(parameterMap);
                objectBaseResult.setHttpCode(200);
                return objectBaseResult;
            }catch (Exception e){
                e.printStackTrace();
            }
            objectBaseResult.setHttpCode(500);
            return objectBaseResult;
        }
}